SQL触发器仅允许年龄足够大的客户购买书籍?

时间:2018-11-24 20:53:18

标签: sql triggers mariadb

我有3个表,personaudiobookaudiobook_purchases。我的数据库正在运行MariaDB。

  • person具有字段:iddate_of_birth;
  • audiobook具有字段:ISBNage_ratingtitle
  • audiobook_purchases具有字段:ISBNcustomer_iddate_of_purchase

我正在尝试编写触发器,以确保当客户尝试购买有声读物时,他们的年龄足以按照有声读物中的age_rating购买。

例如,如果哈利·波特(Harry Potter)和《哲学之石》(The Philosipher's Stone)的年龄为16岁,并且客户的珍妮弗(ID 1)的生日为2010-01-01,则试图购买此书,则该书将被禁止,但Dominick(ID 2 )和date_of_birth 1978-01-01

请有人告诉我一种运行此触发器的方法吗?

1 个答案:

答案 0 :(得分:1)

我不是特别了解MariaDB,因此我的答案可能需要一些调整。

您想在audiobook_purchase上创建一个插入触发器,以便仅在要下订单的人根据audiobook.age_rating足够大时才插入新订单。

首先,您需要找出一种从person.date_of_birth中提取年份的方法。像YEAR()标量函数之类的东西可能会可用。 MariaDB还可以提供NOW()函数,该函数提供当前日期。因此,现在的人年龄为:YEAR(NOW()) - YEAR(person.date_of_birth)

然后,您必须编写插入触发器。棘手的部分是查询person表以从其date_of_birth中获得某人id,然后将其与audiobook.age_rating进行比较。

让我们举个例子。首先,我们声明表模式:

CREATE TABLE person(id, name, date_of_birth);
CREATE TABLE audiobook(isbn, age_rating, title);
CREATE TABLE audiobook_purchases(isbn, customer_id, date_of_purchase);

然后我们输入一些数据:

INSERT INTO person VALUES (10, "jennifer", '2010-01-01');
INSERT INTO person VALUES (20, "dominick", '1978-01-01');
INSERT INTO audiobook VALUES (1234, 16, "harry potter");

然后我们创建触发器:

CREATE TRIGGER check_purchases
AFTER INSERT ON audiobook_purchases
FOR EACH ROW
WHEN (
    SELECT strftime('%Y', 'now') - strftime('%Y', date_of_birth) AS age
    FROM person 
    WHERE new.customer_id=person.id) < (
        SELECT audiobook.age_rating
        FROM audiobook
        WHERE audiobook.isbn=new.isbn)
BEGIN 
    DELETE FROM audiobook_purchases
    WHERE isbn=new.isbn AND 
    customer_id=new.customer_id AND
    date_of_purchase=new.date_of_purchase;
END;

我将触发器分成较小的步骤:

  1. AFTER INSERT ON audiobook_purchases在表audiobook_purchases上创建一个触发器,该触发器将在插入新记录后触发。
  2. FOR EACH ROW将触发器应用于插入的每个新记录。
  3. WHEN子句仅将触发限制为满足其条件的那些记录。条件的<左侧有一个查询,用于选择客户的年龄。右侧有一个查询,用于选择书的年龄等级。注意对new表的引用。该表存储了触发事件的记录(请参见下面的两个示例)。 strftime是一种标量函数,可在SQLite中格式化日期时间戳。你可以阅读: strftime('%Y', 'now')YEAR(NOW()),并且 strftime('%Y', date_of_birth)YEAR(date_of_birth)
  4. 最后在BEGINEND之间,有一些指令将在触发时执行。在这种情况下,只有一条指令可以删除刚刚插入的记录。 MariaDb可以提供ROLLBACK语句,比DELETE语句更有效。

例如,

INSERT INTO audiobook_purchases VALUES (1234, 10, '2018-11-25');

将激活触发器,因为拥有id=10(“詹妮弗”)的客户已经8岁,而拥有isbn=1234的书要求该客户至少16岁,而: >

INSERT INTO audiobook_purchases VALUES (1234, 20, '2018-11-25'); 

该客户已有40岁,因此不会激活触发器。

您必须知道,此解决方案会静默忽略无效订单。我不知道这是否是您想要的行为。

我在SQLite 3.11.0上测试了此触发器,因此它可能与您的SQL解释器不兼容。