Firebird 在触发器内执行过程和语句(该过程的结果作为其中的一部分)

Firebird execute procedure and statement (with result from that procedure as part of it) inside trigger

我想执行更新前触发器,检查一行中的所有字段是否相同并取消更新。我正在使用 Firebird 2.5。

我目前的做法是这样的:

我的代码:

SET TERM ^ ;
ALTER TRIGGER BI_MERILA_STRANKE ACTIVE
BEFORE INSERT OR UPDATE POSITION 0
AS 
declare variable besedilo_primerjave varchar(5000);

BEGIN 
    begin

         if (new.ID_MERILA_STRANKE is null OR new.ID_MERILA_STRANKE = 0) then new.ID_MERILA_STRANKE = gen_id(GEN_ID_MERILA_STRANKE,1);
    end

    begin    
        besedilo_primerjave = execute procedure 
STRING_SESTAVLJEN_ENAKOST_TABEL('MERILA_STRANKE');   -- if this is true then you need to save othervise not

         execute statement besedilo_primerjave || ' THEN BEGIN INSERT INTO SYNC_INFO(TABLE_NAME,ID_COLUMN_NAME,ID_VALUE,DATETIME) 
        VALUES (
            ''MERILA_STRANKE'',
            ''ID_MERILA_STRANKE'',
            NEW.ID_MERILA_STRANKE,
            CURRENT_TIMESTAMP
        );

        END ELSE BEGIN

            exception ENAK_RECORD;

        END';
    end
END^
SET TERM ; ^

当我尝试执行此操作时,出现以下错误:

Token unknown - line 18, column 10
execute

这是这行代码:

execute statement besedilo_primerjave || ' THEN BEGIN INSERT INTO SYNC_INFO(TABLE_NAME,ID_COLUMN_NAME,ID_VALUE,DATETIME)

我没有经常使用 Firebird,所以如果有人知道我做错了什么,或者如果有人知道实现此目的的更好解决方案,请帮助我。

我需要在数据库上做,可能更好的方法是在软件上做,但我做不到。

你对有问题的线路是错误的。实际问题在

besedilo_primerjave = execute procedure STRING_SESTAVLJEN_ENAKOST_TABEL('MERILA_STRANKE'); 

赋值后不能有execute procedure,需要用

execute procedure STRING_SESTAVLJEN_ENAKOST_TABEL('MERILA_STRANKE')
    returning_values :besedilo_primerjave;

您的下一条语句不能像 execute statement cannot be used to execute snippets of PSQL (procedural SQL) like that, it can only execute normal DSQL (dynamic SQL), and you cannot access the context variables (like new) in that way. You would need to pass the required columns from new explicitly as parameter values to execute statement, and you could try if you can get it to work by wrapping the PSQL you try to execute dynamically in an execute block 那样工作,但那样会很快变丑。

我建议您重新考虑您正在做的事情,也许将真正的逻辑写在触发器中,而不是像您现在尝试做的那样完全动态地进行。

这是我基于上面 Mark 的示例并在 Firebird 3.0 中工作的示例:

SET TERM ^ ;
CREATE TRIGGER UMCDB_DRIVER_BI FOR UMCDB_DRIVER ACTIVE
BEFORE INSERT POSITION 0
AS 
BEGIN 
    new.ID = gen_id(GEN_DRIVER, 1);
    new.CREATE_USERID = CURRENT_USER;
    new.CREATE_TS = CURRENT_TIMESTAMP;
    -- Get the hashed value for the driver name.
    execute procedure PRC_NAME_HASH( new.DRVR_FIRST_NAME, new.DRVR_MID_INITS, new.DRVR_LAST_NAME)
        returning_values new.NAME_HASH;
END^
SET TERM ; ^

干得漂亮!谢谢,马克!