如何根据更新/删除的行删除/更新触发器内的记录?

时间:2015-01-05 16:15:37

标签: sql plsql triggers sql-delete

我有一个格式如下的表格

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;
/

1 个答案:

答案 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个触发器更好地执行 - 即:

  • 使用不存在的(非NULL)supervisor_id
  • 阻止插入/更新
  • 删除主管时将所有supervisor_id设置为NULL

有关实例,请参阅http://sqlfiddle.com/#!4/1f8fb/1