我有3个表,person
,audiobook
和audiobook_purchases
。我的数据库正在运行MariaDB。
person
具有字段:id
,date_of_birth
; audiobook
具有字段:ISBN
,age_rating
,title
; audiobook_purchases
具有字段:ISBN
,customer_id
,date_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
。
请有人告诉我一种运行此触发器的方法吗?
答案 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;
我将触发器分成较小的步骤:
AFTER INSERT ON audiobook_purchases
在表audiobook_purchases
上创建一个触发器,该触发器将在插入新记录后触发。FOR EACH ROW
将触发器应用于插入的每个新记录。WHEN
子句仅将触发限制为满足其条件的那些记录。条件的<
左侧有一个查询,用于选择客户的年龄。右侧有一个查询,用于选择书的年龄等级。注意对new
表的引用。该表存储了触发事件的记录(请参见下面的两个示例)。 strftime
是一种标量函数,可在SQLite中格式化日期时间戳。你可以阅读:
strftime('%Y', 'now')
为YEAR(NOW())
,并且
strftime('%Y', date_of_birth)
为YEAR(date_of_birth)
。BEGIN
和END
之间,有一些指令将在触发时执行。在这种情况下,只有一条指令可以删除刚刚插入的记录。 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解释器不兼容。