#sql #triggers #mariadb
Вопрос:
Я пытаюсь автоматизировать некоторые задачи в базе данных, а не в приложении. У нас есть небольшой MariaDB для продажи билетов. Когда билет продан, его статус должен быть установлен в значение NOT_VALID до тех пор, пока не будет произведена оплата. После оплаты билет необходимо установить на ДЕЙСТВИТЕЛЬНЫЙ. Сам счет — фактура находится в таблице «som_accounting», и с помощью справочной таблицы (som_accountingtickets-из-за ленивых дизайнерских решений) он указывает на билеты. Теперь я пытаюсь автоматизировать, чтобы флаг в таблице билетов был установлен на ДЕЙСТВИТЕЛЬНЫЙ, когда столбец PAYMENTSTATUS в таблице учета меняется с ОТКРЫТОГО (1) на ОПЛАЧЕННЫЙ (3).
Когда я использую это на консоли (dbeaver или терминале), это работает нормально:
UPDATE som_ticket SET ID_ticketstatus = 4, activation_date = CURRENT_DATE()
WHERE ticketID IN
(SELECT act.ID_ticket FROM som_accountingticket act
INNER JOIN (SELECT * FROM som_accounting) AS ac
ON ac.accountingID = act.ID_accounting
INNER JOIN (SELECT * FROM som_ticket) AS t2
ON t2.ticketID = act.ID_ticket AND t2.ID_ticketstatus = '1'
WHERE act.ID_accounting = '565');
Теперь я вставил это в триггер и получил ошибку:
CREATE DEFINER=`<user>`@`%` TRIGGER `somt_au_accounting`
AFTER UPDATE
ON `som_accounting`
FOR EACH ROW BEGIN
IF NEW.ID_paymentstatus = 3 AND OLD.ID_paymentstatus = 1 THEN
UPDATE som_ticket SET ID_ticketstatus = '4',
activation_date = CURRENT_DATE()
WHERE ticketID IN
(SELECT act.ID_ticket FROM som_accountingticket act
INNER JOIN (SELECT * FROM som_accounting) AS ac
ON ac.accountingID = act.ID_accounting
INNER JOIN (SELECT * FROM som_ticket) AS t2
ON t2.ticketID = act.ID_ticket
AND t2.ID_ticketstatus = '1'
WHERE act.ID_accounting = OLD.accountingID);
END IF;
END
База данных сообщает об этом:
Error synchronizing data with database
Reason:
SQL-Fehler [08]: (conn:3) Could not read resultset: unexpected end of stream, read 0 bytes from 4
Query is: UPDATE d0294220.som_accounting
SET ID_paymentstatus=?
WHERE accountingID=?, parameters [3,568]
Почему он хорошо работал в консоли, но не в триггере?
MariaDB 10.5.8
Комментарии:
1. Ошибка выглядит так, как будто она вызвана каким-то другим запросом? … Ни одна часть запроса триггера не имеет
SET ID_paymentstatus
.2. Набор нового ID_paymanetstatus выполняется в приложении. Если счет оплачивается, пользователь изменяет это значение в приложении с 1 (еще не оплачено) на 3 (оплачено), и триггер прослушивает это изменение и должен сделать все остальное.
3. Тогда единственное, что я вижу, это то, что запрос, перемещенный в триггер, ссылается на ту же таблицу, которая запускает триггер (при внутреннем соединении), что недопустимо.
Cannot make changes to a table that is already in use (reading or writing) by the statement invoking the stored function.
Эта информация из ограничений триггера MariaDB указана во второй информации о элементе маркера.4. Теперь я разделил работу. Триггер проверяет только, нужно ли что-то делать: если статус оплаты изменился с 1 на 3, затем вызовите хранимую процедуру и передайте идентификатор учетной записи. Процедура выполняет поиск всех билетов для изменения и устанавливает их ДЕЙСТВИТЕЛЬНЫМИ.