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

时间:2013-02-09 14:42:04

标签: database oracle plsql

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

当我在表A中插入一行时,我需要一个触发器,以便它更新表B上的一行:特别是主键与刚刚添加到表A的行的相应外键匹配的行。 p>

因此,例如,表A中的列X是引用表B中的列Y(主键)的外键。当我向表A添加一行时,我需要表B的Z列在其中X列= Y列的行中添加1的数值。

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

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

BEGIN
  UPDATE tableB
  SET columnZ = columnZ + 1
  WHERE tableA.columnX = tableB.columnY;
END test_trig;
/

由于

4 个答案:

答案 0 :(得分:1)

试试这个:

语法将是

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。

答案 1 :(得分:0)

足够开始。

首先 - 让我们解决这个问题 - 这没有很好地规范化 - 你描述的值似乎应该在运行时而不是在数据操作时计算。

考虑以下事项:

将insert = +1添加到列中 - 确定

更新=?并不总是+1我想到的列 - 可能只有当某些其他数据被修改时。例如 - 如果我更新表集合col1 = col1怎么办?也许你想要的也许不是。

删除=?删除是否意味着-1到列?

表示语法:

WHERE tableA.columnX = tableB.columnY;

应该是

WHERE :new.columnX = tableB.columnY;

答案 2 :(得分:0)

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

First Ocasion: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;
/

Second Ocasion: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;
/

第三次曝光: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;
/

答案 3 :(得分:0)

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

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

相关问题