如何根据updated/deleted 行delete/update 记录内部触发器?
How to delete/update records inside trigger based on the updated/deleted row?
我有一个table格式如下
编号 |姓名 | supervisor_id
我创建了一个 "BEFORE INSERT" 触发器来检查 supervisor_id 是否存在于 id 列中,如果不存在,则将空值分配给 supervisor_id。
我正在尝试再写两个触发器。一种是在每次更新 supervisor_id 之前检查 id 列中是否存在 supervisor_id,另一种是如果每个员工的主管被删除,则将 supervisor_id 设置为 NULL。
这是我的代码,当然不能用,请帮忙。
CREATE OR REPLACE TRIGGER EAP_users_TRG3
AFTER DELETE
ON EAP_users
FOR EACH ROW
DECLARE
d NUMBER;
BEGIN
SELECT id INTO d FROM EAP_users WHERE id = :OLD.id;
UPDATE EAP_users SET supervisor = NULL WHERE supervisor = d;
END;
/
这是 "working" 触发器:
CREATE OR REPLACE TRIGGER EAP_users_TRG1
BEFORE INSERT
ON EAP_users
FOR EACH ROW
DECLARE
supervisor EAP_users.supervisor%TYPE;
CURSOR supervisor_CUR IS SELECT idFROM EAP_users;
b BOOLEAN := FALSE;
BEGIN
IF ( :NEW.supervisor IS NOT NULL ) THEN
FOR s IN supervisor_CUR LOOP
IF ( :NEW.supervisor = s.id ) THEN
b := TRUE;
END IF;
END LOOP;
IF (b = FALSE) THEN
:NEW.supervisor := NULL;
END IF;
END IF;
END;
/
根据您的问题的定义,您正在尝试强制执行数据的引用完整性。在那种情况下,触发器可能不是正确的工具。引用 Oracle's documentation:
You can use both triggers and integrity constraints to define and enforce any type of integrity rule. However, Oracle strongly recommends that you use triggers to constrain data input only in the following situations:
- [...]
- When a required referential integrity rule cannot be enforced using the following integrity constraints:
- NOT NULL, UNIQUE
- PRIMARY KEY
- FOREIGN KEY
- CHECK
- DELETE CASCADE
- DELETE SET NULL
在那种特定情况下,您应该 使用 FOREIGN KEY
约束并使用 DELETE SET NULL
修饰符。假设您在 id
上有一个索引,您只需要:
ALTER TABLE EAP_users
ADD CONSTRAINT EAP_users_supervisor_cst
FOREIGN KEY (supervisor_id)
REFERENCES EAP_users(id)
ON DELETE SET NULL;
这个简单的参照完整性约束可能会更好地执行与您的 3 个触发器相同的事情——即:
- 防止 insert/update 使用不存在的(非 NULL)
supervisor_id
- 删除主管
时将所有supervisor_id
设置为NULL
有关实例,请参阅 http://sqlfiddle.com/#!4/1f8fb/1。
我有一个table格式如下
编号 |姓名 | supervisor_id
我创建了一个 "BEFORE INSERT" 触发器来检查 supervisor_id 是否存在于 id 列中,如果不存在,则将空值分配给 supervisor_id。
我正在尝试再写两个触发器。一种是在每次更新 supervisor_id 之前检查 id 列中是否存在 supervisor_id,另一种是如果每个员工的主管被删除,则将 supervisor_id 设置为 NULL。
这是我的代码,当然不能用,请帮忙。
CREATE OR REPLACE TRIGGER EAP_users_TRG3
AFTER DELETE
ON EAP_users
FOR EACH ROW
DECLARE
d NUMBER;
BEGIN
SELECT id INTO d FROM EAP_users WHERE id = :OLD.id;
UPDATE EAP_users SET supervisor = NULL WHERE supervisor = d;
END;
/
这是 "working" 触发器:
CREATE OR REPLACE TRIGGER EAP_users_TRG1
BEFORE INSERT
ON EAP_users
FOR EACH ROW
DECLARE
supervisor EAP_users.supervisor%TYPE;
CURSOR supervisor_CUR IS SELECT idFROM EAP_users;
b BOOLEAN := FALSE;
BEGIN
IF ( :NEW.supervisor IS NOT NULL ) THEN
FOR s IN supervisor_CUR LOOP
IF ( :NEW.supervisor = s.id ) THEN
b := TRUE;
END IF;
END LOOP;
IF (b = FALSE) THEN
:NEW.supervisor := NULL;
END IF;
END IF;
END;
/
根据您的问题的定义,您正在尝试强制执行数据的引用完整性。在那种情况下,触发器可能不是正确的工具。引用 Oracle's documentation:
You can use both triggers and integrity constraints to define and enforce any type of integrity rule. However, Oracle strongly recommends that you use triggers to constrain data input only in the following situations:
- [...]
- When a required referential integrity rule cannot be enforced using the following integrity constraints:
- NOT NULL, UNIQUE
- PRIMARY KEY
- FOREIGN KEY
- CHECK
- DELETE CASCADE
- DELETE SET NULL
在那种特定情况下,您应该 使用 FOREIGN KEY
约束并使用 DELETE SET NULL
修饰符。假设您在 id
上有一个索引,您只需要:
ALTER TABLE EAP_users
ADD CONSTRAINT EAP_users_supervisor_cst
FOREIGN KEY (supervisor_id)
REFERENCES EAP_users(id)
ON DELETE SET NULL;
这个简单的参照完整性约束可能会更好地执行与您的 3 个触发器相同的事情——即:
- 防止 insert/update 使用不存在的(非 NULL)
supervisor_id
- 删除主管 时将所有
supervisor_id
设置为NULL
有关实例,请参阅 http://sqlfiddle.com/#!4/1f8fb/1。