Stored procedures 触发器内的Firebird execute过程和语句(该过程的结果作为其一部分)

Stored procedures 触发器内的Firebird execute过程和语句(该过程的结果作为其一部分),stored-procedures,triggers,firebird,firebird2.5,Stored Procedures,Triggers,Firebird,Firebird2.5,我想执行一个before update触发器,它检查一行中的所有字段是否相同并取消更新。我用的是火鸟2.5 我目前的做法是: 使用过程获取具有old.FIELD,new.FIELD的所有字段名称。大概是这样的: IF (new.LOCATION IS DISTINCT FROM old.LOCATION) OR (new.NAME IS DISTINCT FROM old.NAME) 。。。过程的返回类型是Varchar(1000)。这很有效。程序如下:STRING_SESTAVLJEN_E

我想执行一个before update触发器,它检查一行中的所有字段是否相同并取消更新。我用的是火鸟2.5

我目前的做法是:

  • 使用过程获取具有
    old.FIELD
    new.FIELD
    的所有字段名称。大概是这样的:

    IF (new.LOCATION IS DISTINCT FROM
    old.LOCATION) OR (new.NAME IS DISTINCT FROM old.NAME)
    
    。。。过程的返回类型是
    Varchar(1000)
    。这很有效。程序如下:
    STRING_SESTAVLJEN_ENAKOST_TABEL('MERILA_STRANKE')

  • 如果此条件为真,我想在
    SYNC_INFO
    表中插入一些值,然后继续更新行。如果条件为false,我想取消更新行。我通过抛出一个异常来实现这一点
我的代码:

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 ; ^
当我尝试执行此操作时,会出现以下错误:

令牌未知-第18行第10列
执行

这是一行代码:

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 STRING_SESTAVLJEN_ENAKOST_TABEL('MERILA_STRANKE')
    returning_values :besedilo_primerjave;
您的下一条语句不能工作,因为它不能用于执行类似的PSQL(过程SQL)片段,它只能执行普通DSQL(动态SQL),并且您不能以这种方式访问上下文变量(如
new
)。您需要将
new
中所需的列作为参数值显式地传递给
execute语句
,如果您可以通过将尝试动态执行的PSQL包装在一个中来让它工作,那么您可以尝试,但这会很快变得难看


我建议你重新考虑一下你在做什么,也许在触发器中写下真正的逻辑,而不是像你现在尝试做的那样尝试完全动态地完成它。

以下是我基于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 ; ^

工作得很漂亮!谢谢你,马克

谢谢你。。。我把它修好了一点。。。现在我得到另一个错误:/@Pajkec正如我所说,您当前的解决方案不能像那样工作。您能解释一下原因吗?我的意思是,如果我直接运行代码或使用execute语句(字符串语句与编写的代码完全相同)运行代码,会有什么区别。@Pajkec重新表述我的答案,因为execute语句不是这样工作的:它只支持DSQL,不支持PSQL语句。它使用的API与您从应用程序或查询工具执行查询时使用的API相同,但也不支持PSQL。。。那我该怎么办?我真的不想用长符号写下所有的IF语句,当我要添加一个专栏时,我每次都需要更改它……我回滚了你的编辑,因为它改变了问题的范围。如果遇到新问题,请发布新问题(即使是相同的代码)。