Относительно простой вопрос. Я пытаюсь выполнить оператор и проверить значение перед настройкой значения INSERT в триггере firebird. Я видел много примеров, в которых новое значение оценивается, а затем выполняются последующие операторы, но ни один из них, как я хочу. Легче показать...
SET TERM ^ ;
CREATE TRIGGER STOP_PREMIX_INSERT_PRODUCEDD FOR PRODUCEDD ACTIVE
BEFORE INSERT OR UPDATE POSITION 0
AS
BEGIN
IF ('SELECT COUNT(*) FROM RECIPESTEPS rs INNER JOIN RECIPES r on r.RECIPEID=rs.RECIPEID INNER JOIN PRODUCEDH h on h.RECIPEID=r.RECIPEID WHERE h.BATCHID=' || new.BATCHID || ' AND ' || new.SEQUENCENO || '=rs.SEQUENCENO AND ' || new.COMMODITYID || '=rs.COMMODITYID AND rs.NONWEIGHED=17;' > 0) then
new.BATCHID=-1;
END^
SET TERM ; ^
Я пытаюсь проверить наличие фрагмента данных в другой таблице перед выполнением изменения значения в новой записи.
Обычно IF (new.ID = 0) выполняет оператор 'blah'; будет работать, но когда я пишу этот триггер, он синтаксически принимается, но при изменении значения я получаю следующее сообщение об ошибке:
арифметическое исключение, числовое переполнение или усечение строки усечение строки справа При триггере 'STOP_PREMIX_INSERT_PRODUCECEDD' строка: 6, столбец: 5
Я могу быть с запятой или это может быть просто невозможно, в любом случае, любая помощь приветствуется.
Ответ 1 · рейтинг 2 · Mark Rotteveel
Причина, по которой это не работает, заключается в том, что вы создаете строку, а затем сравниваете ее с целым числом. Полученное преобразование завершается ошибкой. Тот факт, что строка содержит что-то похожее на SQL, на самом деле не выполняет его.
Вместо этого вам нужно выполнить запрос, например, используя EXISTS:
SET TERM ^ ;
CREATE TRIGGER STOP_PREMIX_INSERT_PRODUCEDD FOR PRODUCEDD ACTIVE
BEFORE INSERT OR UPDATE POSITION 0
AS
BEGIN
IF (EXISTS (SELECT *
FROM RECIPESTEPS rs
INNER JOIN RECIPES r on r.RECIPEID=rs.RECIPEID
INNER JOIN PRODUCEDH h on h.RECIPEID=r.RECIPEID
WHERE h.BATCHID = new.BATCHID
AND rs.SEQUENCENO = new.SEQUENCENO
AND rs.COMMODITYID = new.COMMODITYID
AND rs.NONWEIGHED = 17)) then
new.BATCHID=-1;
END^
SET TERM ; ^
Это, вероятно, более эффективно, чем select count(*), как в другом ответе, потому что Firebird не нужно будет запрашивать все строки, просто проверьте, есть ли одна или несколько.
Ответ 2 · рейтинг 2 · Maxim Votyakov
Это должно быть так:
SET TERM ^ ;
CREATE TRIGGER STOP_PREMIX_INSERT_PRODUCEDD FOR PRODUCEDD ACTIVE
BEFORE INSERT OR UPDATE POSITION 0
AS
declare variable CNT integer;
BEGIN
SELECT COUNT(*) FROM RECIPESTEPS rs INNER JOIN RECIPES r on r.RECIPEID=rs.RECIPEID INNER JOIN PRODUCEDH h on h.RECIPEID=r.RECIPEID WHERE h.BATCHID = new.BATCHID AND new.SEQUENCENO = rs.SEQUENCENO AND new.COMMODITYID = rs.COMMODITYID AND rs.NONWEIGHED=17 into :CNT;
IF (CNT > 0) then
new.BATCHID=-1;
END^
SET TERM ; ^
Я не могу проверить, будет ли это работать, потому что у меня нет вашей базы данных, но теперь вы должны увидеть, как это сделать правильно.