我有一个格式如下的表格
id |名字| supervisor_id
我创建了一个“BEFORE INSERT”触发器,用于检查supervisor_id是否存在于id列中,如果不存在,则将空值分配给supervisor_id。
我正在尝试再写两个触发器。在每次更新supervisor_id之前检查supervisor_id是否存在于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;
/
这是“工作”触发器:
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;
/
答案 0 :(得分:2)
根据您问题的定义,您正在尝试强制执行数据的参照完整性。在这种情况下,触发器可能不正确的工具。引用Oracle's documentation:
您可以使用触发器和完整性约束来定义和实施任何类型的完整性规则。但是,Oracle强烈建议您仅在以下情况下使用触发器来约束数据输入:
- [...]
- 使用以下完整性约束无法强制执行必需的参照完整性规则时:
- NOT NULL,UNIQUE
- PRIMARY KEY
- 外键
- CHECK
- 删除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个触发器更好地执行 - 即:
supervisor_id
supervisor_id
设置为NULL 有关实例,请参阅http://sqlfiddle.com/#!4/1f8fb/1。