Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Запрос проверки SQL триггера Firebird

Автор вопроса: MxMaveОтветов: 2

Относительно простой вопрос. Я пытаюсь выполнить оператор и проверить значение перед настройкой значения 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

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

  • Не то чтобы я знал Firebird, но похоже, что вы проверяете, больше ли строка SQL нуля. Может быть, вам нужно выполнить строку и сравнить результат? Joachim Isaksson 09.03.2016

sqltriggersfirebirdddl

Ответы

Ответ 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 ; ^

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы