5

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

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

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

根据我对触发器的有限理解,这是我迄今为止在 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

4 回答 4

5

尝试这个 :

语法将是

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。

于 2013-02-09T15:16:10.137 回答
0

足够好的开始。

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

考虑以下:

插入 = +1 到列 - 好的

更新=?我想并不总是对该列 +1 - 可能仅在修改某些其他数据时。例如 - 如果我更新表一个集合 col1=col1。也许你想要的也许不是。

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

对于语法:

WHERE tableA.columnX = tableB.columnY;

应该

WHERE :new.columnX = tableB.columnY;
于 2013-02-09T15:04:36.493 回答
0

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

第一种情况: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;
/

第三种情况: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;
/
于 2013-02-09T15:17:54.547 回答
0

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

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

于 2013-02-09T22:23:30.533 回答