Database PL/SQL触发器从一个表上的INSERT更新另一个表

Database PL/SQL触发器从一个表上的INSERT更新另一个表,database,oracle,plsql,Database,Oracle,Plsql,我正在使用SQL和Oracle数据库,需要一些帮助-触发器是我很难理解的东西 我需要一个触发器,用于在表a中插入一行以更新表B中的一行:特别是主键与刚刚添加到表a中的行的对应外键匹配的行 例如,表A中的列X是一个外键,它引用表B中的列Y(主键)。当我将一行添加到表a中时,我需要将表B的Z列添加到其数值中,其中X列=Y列 基于我对触发器的有限理解,这就是我迄今为止在SQL中所能得到的,以防它有所帮助(我意识到它不是很好,将其视为伪代码): 谢谢好的开始 首先,让我们把它放在一边-这不是很好的标准化

我正在使用SQL和Oracle数据库,需要一些帮助-触发器是我很难理解的东西

我需要一个触发器,用于在表a中插入一行以更新表B中的一行:特别是主键与刚刚添加到表a中的行的对应外键匹配的行

例如,表A中的列X是一个外键,它引用表B中的列Y(主键)。当我将一行添加到表a中时,我需要将表B的Z列添加到其数值中,其中X列=Y列

基于我对触发器的有限理解,这就是我迄今为止在SQL中所能得到的,以防它有所帮助(我意识到它不是很好,将其视为伪代码):

谢谢

好的开始

首先,让我们把它放在一边-这不是很好的标准化-您描述的值似乎应该在运行时计算,而不是在数据操作时

考虑以下几点:

在列中插入=+1-确定

更新=?我想,并非总是对列加1-可能只有在修改某些其他数据时才加1。例如,如果我更新表a集合col1=col1会怎么样。也许是你想要的,也许不是

删除=?删除是指列中的-1吗

对于语法:

WHERE tableA.columnX = tableB.columnY;
应该是

WHERE :new.columnX = tableB.columnY;
试试这个:

语法将是

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT OR UPDATE ON tableA
FOR EACH ROW

BEGIN
  UPDATE tableB
  SET columnZ = columnZ + 1
  WHERE tableB.columnX = :NEW.columnX;
END test_trig; 
/

:new.columnX引用表A columnX。

如果tableB.columnZ表示引用的tableA记录的计数,则在tableA更新时触发没有意义,除非tableA的引用列可以更改

第一个位置:tableA.ReferenceColumn未更改:

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT ON tableA
FOR EACH ROW
BEGIN

  UPDATE tableB
  SET columnZ = columnZ + 1
  WHERE tableB.columnX = :NEW.columnX;
END test_trig;
/
第二个位置:tableA.ReferenceColumn确实发生了变化:

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT OR UPDATE OF columnX ON tableA
FOR EACH ROW

BEGIN

  IF UPDATING AND nvl(:OLD.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ - 1
      WHERE tableB.columnX = :OLD.columnX;
  END IF:

  IF nvl(:NEW.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ + 1
      WHERE tableB.columnX = :NEW.columnX;  
  END IF;

END test_trig;
/
创建或替换触发器测试触发器
插入或更新表A上的columnX后
每行
开始
如果正在更新和nvl(:OLD.columnX,0)0,则
更新表B
设置columnZ=columnZ-1
其中tableB.columnX=:OLD.columnX;
如果:
如果nvl(:NEW.columnX,0)0,则
更新表B
设置columnZ=columnZ+1
其中tableB.columnX=:NEW.columnX;
如果结束;
结束测试触发;
/
第三个位置:可以删除tablaA记录:

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT OR DELETE OR UPDATE OF columnX ON tableA
FOR EACH ROW

BEGIN
  IF (UPDATING OR DELETING) AND nvl(:OLD.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ - 1
      WHERE tableB.columnX = :OLD.columnX;
  END IF:

  IF nvl(:NEW.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ + 1
      WHERE tableB.columnX = :NEW.columnX;  
  END IF;
END test_trig;
/
创建或替换触发器测试触发器
插入、删除或更新表格A上的columnX后
每行
开始
如果(更新或删除)和nvl(:OLD.columnX,0)为0,则
更新表B
设置columnZ=columnZ-1
其中tableB.columnX=:OLD.columnX;
如果:
如果nvl(:NEW.columnX,0)0,则
更新表B
设置columnZ=columnZ+1
其中tableB.columnX=:NEW.columnX;
如果结束;
结束测试触发;
/

我猜您正在实现某种机制,用于(A)保存历史记录(B)计数器或(C)数据完整性问题。 如果是这种情况,我建议使用pl/sql包执行更新,该包将处理所有必要的更新/其他DML操作。 通过pl/sql包更新数据是应用程序的最佳实践。通过这种方式,您可以在内部控制流程,并且更易于维护。另外,当你忘了在那张桌子上有一个触发器时,你可以在将来保存你的自我问题

我可以为您提供一个关于触发器的提示-在您决定使用触发器之前,请确保您已经用尽了所有其他可能性

CREATE OR REPLACE TRIGGER test_trig
AFTER INSERT OR DELETE OR UPDATE OF columnX ON tableA
FOR EACH ROW

BEGIN
  IF (UPDATING OR DELETING) AND nvl(:OLD.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ - 1
      WHERE tableB.columnX = :OLD.columnX;
  END IF:

  IF nvl(:NEW.columnX,0) <> 0 THEN
      UPDATE tableB
      SET columnZ = columnZ + 1
      WHERE tableB.columnX = :NEW.columnX;  
  END IF;
END test_trig;
/