Oracle 检查新员工不存在的触发器

Oracle 检查新员工不存在的触发器,oracle,plsql,triggers,oracle-apex,Oracle,Plsql,Triggers,Oracle Apex,我试图创建一个触发器来检查emp_mb表中是否已经存在员工,并收到此错误消息 ORA-00969:关键字上缺少 有什么想法吗 CREATE OR REPLACE TRIGGER adduser_mb BEFORE INSERT OR UPDATE emp_id ON emp_mb FOR EACH ROW DECLARE DUMMY INTEGER; BEGIN SELECT COUNT(*) INTO DUMMY FROM emp_mb WHERE

我试图创建一个触发器来检查emp_mb表中是否已经存在员工,并收到此错误消息

ORA-00969:关键字上缺少

有什么想法吗

CREATE OR REPLACE TRIGGER adduser_mb
BEFORE 
INSERT OR UPDATE emp_id 
ON emp_mb
FOR EACH ROW 
DECLARE 
DUMMY INTEGER;
BEGIN 
     SELECT COUNT(*) INTO DUMMY 
     FROM emp_mb 
     WHERE emp_id = :new.emp_id

     IF (dummy > 0) 
        THEN raise_application_error(-20501 
        'Employee ID' || :new.emp_id || ' already exists');
END IF;
END;

我想你错过了一个

BEFORE 
INSERT OR UPDATE OF emp_id 
ON emp_mb

顺便说一下,您可以只使用一个唯一的约束,不是吗?

您不能在单个(非复合)触发器中实际执行此操作

emp\u mb
上的行级触发器通常无法查询
emp\u mb
。一旦解决了语法问题,就会出现一个变异表异常

确保
emp\u id
唯一的正确方法是在表上创建唯一约束

alter table emp_mb
  add( constraint uk_emp_id unique (emp_id) );
如果你真的,真的,真的想用触发器实现这一点,你需要多个触发器(或者如果你使用11.2的话,需要一个实现多个触发器的复合触发器)。您需要一个声明
emp\u id
值集合的包。您需要一个before语句触发器来初始化该集合。您需要一个行级触发器,将
:new.emp\u id
值插入到该包的集合中。然后需要一个after语句触发器,它遍历集合并执行检查。这是许多需要实现、调试和维护的动态部分


但这实际上比代码的激增更糟糕——您还需要实现自己的序列化机制。否则,假设您允许系统中有多个用户,则两个会话都可以插入具有相同
emp\u id
的行,使每个会话的检查成功,然后使两个会话都提交,从而在表中留下重复的值。这意味着您还需要实现一些逻辑,以确保在任何时间点只有一个会话可以将数据插入此表中。反过来,这将大大降低系统的可伸缩性,并很可能导致维护问题,其中会话持有锁,阻塞系统中的所有其他人,直到DBA找到并杀死他们。

为什么不使用唯一约束或主键?直到DBA找到并杀死会话,还是开发人员?@AlexPoole-取决于DBA以及他或她处于何种状态。这两种选择都有效。