Firebird触发,更新其他表字段

时间:2013-01-31 08:50:25

标签: triggers sql-update firebird

是否可以(我假设:是)从触发器(Firebird 2.5)更新其他表。 例如,我有一个表X ,更新后触发器如下:

begin
  if  (new.CODE<>old.CODE)  then
  BEGIN
  post_event  'CODE_CHANGE';
  UPDATE Y SET CODE=10 WHERE ID=1;
  END
end

begin
  if  (new.CODE<>old.CODE)  then
  BEGIN
  post_event  'CODE_CHANGE';
  EXECUTE STATEMENT ('UPDATE Y SET CODE=10 WHERE ID=1');
  END
end

但它不起作用(表格Y 不会改变)。

触发器的完整定义(为了更好地理解)

SET TERM ^^ ;
CREATE TRIGGER ABC FOR X ACTIVE AFTER INSERT OR UPDATE OR DELETE POSITION 0 AS
begin
  if  (new.CODE<>old.CODE)  then
  BEGIN
  post_event  'CODE_CHANGE';
EXECUTE STATEMENT ('UPDATE Y SET CODE=10 WHERE ID=1');
  END
  post_event 'CHANGE';
end ^^

第二个问题:如何为UPDATE命令提供参数(对于表Y ) - 我的意思是我想在上面的代码中放置 10 “ > new.CODE (来自表格X 的新值)类似这样的内容:

UPDATE Y SET CODE=new.CODE WHERE ID=1

感谢您的建议。

ARTIK

1 个答案:

答案 0 :(得分:2)

是的,您可以操纵触发器中的任何表,但不限于与触发器关联的表。所以问题是为什么触发器中的UPDATE语句不起作用?我看到三种可能性:

  1. if (new.CODE<>old.CODE) then声明。如果new的{​​{1}}或old值为codeNULL部分将无法运行。有关完整说明,请参阅Firebird Null Guide。这里的解决方案是使用DISTINCT operator。当然,如果then值没有改变,那么if语句也“失败”,但这应该是显而易见的:)另外,如果你收到code事件,你可以确定if staement运行。 另请注意,在多操作触发器中,如果触发器由CODE_CHANGE触发,则NEW将为NULL,如果触发器为DELETE,则OLDNULLINSERT解雇。所以你的触发器只能在UPDATE语句的情况下按预期工作。您可能希望将其拆分为三个不同的触发器。
  2. 更新的where部分失败,即表格Y中没有ID = 1的记录。可能的解决方案是使用UPDATE OR INSERT statement
  3. 您实际上是commit这笔交易吗?如果您将其回滚,则不仅会在“主表”中回滚所有表中的更改。
  4. 从第二个问题开始 - 是的UPDATE语句看起来没问题,在任何语句中使用触发器上下文变量都是有效的。您可以在语句中使用其前缀为冒号,即

    来使用其他变量
    UPDATE Y SET CODE = :SomeVariable WHERE ID=1