Firebird在触发器内运行execute语句

时间:2018-01-05 11:54:30

标签: triggers firebird

我编写了一个程序STRING_SESTAVLJEN_ENAKOST_TABEL('MERILA_STRANKE'),它生成了我想要执行的代码的一部分(一些if if语句)

        IF ((new.LOKACIJA                        IS DISTINCT FROM old.LOKACIJA                       )
        OR (new.MODIFIED                        IS DISTINCT FROM old.MODIFIED                       )
        OR (new.KARAKTERISTIKE                  IS DISTINCT FROM old.KARAKTERISTIKE                 )
        OR (new.LETNIK                          IS DISTINCT FROM old.LETNIK                         )
        OR (new.ID_PNS_CERT_POS                 IS DISTINCT FROM old.ID_PNS_CERT_POS                )
        OR (new.ID_PNS_CERT_POS                 IS DISTINCT FROM old.ID_PNS_CERT_POS                ))

我希望在触发器中调用它,然后添加一些代码并将它们一起运行。

代码是:

    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    

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

             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 ; ^

现在,当我运行更新并触发触发器时,我收到此错误:

  

SQL消息:-104无效令牌

     

引擎代码:335544569引擎消息:动态SQL错误SQL   错误代码= -104令牌未知 - 第1行,第1列IF

另一方面,如果我这样写:

    SET TERM ^ ;
    ALTER TRIGGER BI_MERILA_STRANKE ACTIVE
    BEFORE INSERT OR UPDATE POSITION 0
    AS 
    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    

            IF ((new.LOKACIJA                        IS DISTINCT FROM old.LOKACIJA                       )
            OR (new.MODIFIED                        IS DISTINCT FROM old.MODIFIED                       )
            OR (new.KARAKTERISTIKE                  IS DISTINCT FROM old.KARAKTERISTIKE                 )
            OR (new.LETNIK                          IS DISTINCT FROM old.LETNIK                         )
            OR (new.ID_PNS_CERT_POS                 IS DISTINCT FROM old.ID_PNS_CERT_POS                )
            OR (new.ID_PNS_CERT_POS                 IS DISTINCT FROM old.ID_PNS_CERT_POS                ))
            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 ; ^

它可以正常工作。我不明白为什么它不会运行,如果是或多或少相同的代码。

1 个答案:

答案 0 :(得分:3)

正如我在上一个问题中所提到的,execute statement不能用于执行PSQL(程序SQL)的片段,它只能执行普通的DSQL(动态SQL)。由于它不了解PSQL,因此“{token}”会出现“令牌未知 - 如果”错误,因为if在DSQL中无效。

execute statement相当于自己从查询工具或应用程序执行SQL(它使用相同的API),你也不能在那里使用if

使用execute block语句存在漏洞,但仍然不允许您访问NEW(或OLD)触发器上下文变量,除非作为参数显式传递,这将否定动态生成的代码在此上下文中的大部分用处。

唯一真正的解决方案是编写触发器而不是动态执行,也许使用代码生成器(我不确定是否存在,否则你需要自己编写)。