Jaa*_*nna 11 oracle triggers plsql oracle11g
假设我们在表中有3条记录:orig_tab
---------------------------------------------
| PK | Name | Address | Postal Code |
---------------------------------------------
| 1 | AA | Street1 | 11111 |
| 2 | BB | Street2 | 22222 |
| 3 | CC | Street3 | 33333 |
---------------------------------------------
Run Code Online (Sandbox Code Playgroud)
现在数据发生了变化:
---------------------------------------------
| PK | Name | Address | Postal Code |
---------------------------------------------
| 1 | AA | Street1 | 11111 |
| 2 | BB | Street2 | 44444 |
| 3 | CC | Dtreet7 | 33333 |
---------------------------------------------
Run Code Online (Sandbox Code Playgroud)
客户想要的是更新记录,只有更新的列(是的,我知道它没有任何意义,但他们使用了一些20世纪70年代的旧系统,他们想要做一些记录等).所以报告表应该是这样的:
---------------------------------------------
| PK | Name | Address | Postal Code |
---------------------------------------------
| 2 | | | 44444 |
| 3 | | Dtreet7 | |
---------------------------------------------
Run Code Online (Sandbox Code Playgroud)
这就是我试过的:
CREATE OR REPLACE TRIGGER vr_reporting_trigger
AFTER UPDATE ON orig_tab
FOR EACH ROW
BEGIN
IF inserting THEN
INSERT INTO rep_tab(pk, name, address, code)
SELECT :new.pk, :new.name, :new.address, :new,code FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM rep_tab WHERE pk = :new.pk);
UPDATE rep_tab t SET t.name = :new.name, t.address = :new.address, t.code = :new.code
WHERE t.pk = :new.pk;
ELSIF updating THEN
IF :new.pk <> :old.pk THEN
UPDATE rep_tab t
SET t.name = :new.name, t.address = :new.address, t.code =: new.code
WHERE t.pk = :old.pk ;
END IF;
MERGE INTO rep_tab d
USING DUAL ON (d.pk = :old.pk)
WHEN MATCHED THEN
UPDATE SET d.name = :new.name, d.address = :new.address, d.code =: new.code
WHEN NOT MATCHED THEN
INSERT (d.pk,d.name, d.address, d.code) VALUES (:new.pk,:new.name, new.address, new.code);
END IF;
END;
Run Code Online (Sandbox Code Playgroud)
有了这个解决方案,我得到:
---------------------------------------------
| PK | Name | Address | Postal Code |
---------------------------------------------
| 2 | BB | Street2 | 44444 |
| 3 | CC | Dtreet7 | 33333 |
---------------------------------------------
Run Code Online (Sandbox Code Playgroud)
我知道在更新语句时插入claus中的某处,但我无法弄清楚如何根据我的要求更改此claus.有什么建议吗?
提前致谢.
Flo*_*ita 22
你需要这个:
在UPDATE触发器中,可以使用UPDATING条件谓词指定列名,以确定是否正在更新命名列.例如,假设触发器定义如下:
CREATE OR REPLACE TRIGGER ...
... UPDATE OF Sal, Comm ON Emp_tab ...
BEGIN
... IF UPDATING ('SAL') THEN ... END IF;
END;
Run Code Online (Sandbox Code Playgroud)
仅针对更改的值触发。
举个例子(仅NOT NULL支持)(带有 NULL 的比较运算符始终返回 FALSE):
CREATE OR REPLACE TRIGGER trigger_department_update
BEFORE UPDATE OF
department_id,
cluster_id,
division_id,
macroregion_id,
address,
email
ON cl_department
FOR EACH ROW
BEGIN
IF (
:new.department_id != :old.department_id
OR :new.cluster_id != :old.cluster_id
OR :new.division_id != :old.division_id
OR :new.macroregion_id != :old.macroregion_id
OR :new.address != :old.address
OR :new.email != :old.email
)
THEN :new.update_date := CURRENT_TIMESTAMP;
END IF;
END;
Run Code Online (Sandbox Code Playgroud)
有了 NULL 支持(感谢本文下面评论中的@Oleg )(感谢@Chris Bandy的回答):
CREATE OR REPLACE TRIGGER trigger_department_update
BEFORE UPDATE OF
department_id,
cluster_id,
division_id,
macroregion_id,
address,
email
ON cl_department
FOR EACH ROW
BEGIN
IF (
((:new.department_id <> :old.department_id OR :new.department_id IS NULL OR :old.department_id IS NULL) AND NOT (:new.department_id IS NULL AND :old.department_id IS NULL))
OR ((:new.cluster_id <> :old.cluster_id OR :new.cluster_id IS NULL OR :old.cluster_id IS NULL) AND NOT (:new.cluster_id IS NULL AND :old.cluster_id IS NULL))
OR ((:new.division_id <> :old.division_id OR :new.division_id IS NULL OR :old.division_id IS NULL) AND NOT (:new.division_id IS NULL AND :old.division_id IS NULL))
OR ((:new.macroregion_id <> :old.macroregion_id OR :new.macroregion_id IS NULL OR :old.macroregion_id IS NULL) AND NOT (:new.macroregion_id IS NULL AND :old.macroregion_id IS NULL))
OR ((:new.address <> :old.address OR :new.address IS NULL OR :old.address IS NULL) AND NOT (:new.address IS NULL AND :old.address IS NULL))
OR ((:new.email <> :old.email OR :new.email IS NULL OR :old.email IS NULL) AND NOT (:new.email IS NULL AND :old.email IS NULL))
)
THEN :new.update_date := CURRENT_TIMESTAMP;
END IF;
END;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25531 次 |
| 最近记录: |