2

是否有可能(我假设:是)从触发器(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 ) - 我的意思是我想在上面的代码中放入new.CODE(来自表 X的新值)而不是值“ 10 ”,如下所示:

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

谢谢你的建议。

阿尔蒂克

4

1 回答 1

2

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

  1. if (new.CODE<>old.CODE) then声明。如果其中一个newold值是,codeNULLthen部分将不会运行。有关完整说明,请参阅Firebird Null 指南。这里的解决方案是使用DISTINCToperator。当然,如果code值没有改变,那么 if 语句也会“失败”,但这应该很明显 :) 此外,如果您收到CODE_CHANGE事件,您可以确定 if 语句运行。另请注意,在多动作触发器中,如果触发器被触发,则NEW将是NULL,如果触发器被触发DELETEOLDNULLINSERT. 因此,您的触发器仅在 UPDATE 语句的情况下按预期工作。您可能希望将其拆分为三个不同的触发器。
  2. 您更新的where部分失败,即表 Y 中没有 ID = 1 的记录。可能的解决方案是使用UPDATE OR INSERTstatement
  3. 你真的commit交易吗?如果你回滚它,所有表中的更改都会回滚,而不仅仅是“主表”。

至于您的第二个问题 - 是的,您的 UPDATE 语句看起来不错,在任何语句中使用触发器上下文变量都是有效的。您可以在语句中使用其他变量,方法是在它们前面加上冒号,即

UPDATE Y SET CODE = :SomeVariable WHERE ID=1
于 2013-01-31T11:22:41.333 回答