SQL Trigger, чтобы позволить только клиентам, которые достаточно взрослые, чтобы купить книгу? - PullRequest
0 голосов
/ 24 ноября 2018

У меня есть 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 в аудиокниге.

Например, если у Гарри Поттера и Философского камня был возрастной рейтинг 16, а у покупательницы Дженнифер (ID 1) с датой рождения 2010-01-01 пытался купить эту книгу, это не было бы разрешено, но Доминику (ID 2) с date_of_birth 1978-01-01 было бы разрешено.

Пожалуйста, кто-то может показать мне способ запуска этого триггера?

1 Ответ

0 голосов
/ 25 ноября 2018

Я не знаю 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. Наконец, между BEGIN и END есть инструкции, которые будут выполняться при запуске.В этом случае есть одна инструкция, которая удаляет только что вставленную запись.MariaDb может предоставить оператор ROLLBACK, который может быть более эффективным, чем оператор DELETE.

Так, например:

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

активирует триггер, потому чтоклиент с id=10 ('jennifer') - 8 лет, а книга с isbn=1234 требует, чтобы клиенту было не менее 16 лет, в то время как:

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

не активирует триггер,потому что этому клиенту 40 лет.

Вы должны знать, что это решение молча игнорирует неверный заказ.Я не знаю, является ли это вашим желаемым поведением.

Я тестировал этот триггер на SQLite 3.11.0, поэтому он может быть несовместим с вашим интерпретатором SQL.

...