最近在看PL/SQL相关的内容,把书上的例子在机器上运行一下,
有一些问题请教大家。
1.使用触发器实现级联更新
CREATE OR REPLACE TRIGGER tr_update_cascade
BEFORE UPDATE OF deptno ON emp
FOR EACH ROW
BEGIN
  UPDATE emp SET deptno=:new.deptno
  WHERE deptno=:old.deptno
END;表emp          表dept
empno(主键)    deptno(主键)
deptno(外键)我运行下面的语句修改表dept中的数据,
SQL> update dept set deptno=120 where deptno=100;
出现以下错误信息:
ORA-02292: 违反完整约束条件 (LNCF.EMP_DEPTNO_FK) - 已找到子记录日志1)看起来触发器没有起到作用,这是什么原因??
2)new.deptno和old.deptno中的"new"和"old"什么意思,没定义就可以使用吗??
2.定义只能在9:00-17:00之间在emp表上执行DML操作的触发器
CREATE OR REPLACE TRIGGER tr_emp_time
BEFORE INSERT OR UPDATE OR DELETE ON emp
BEGIN
  IF to_char(SYSDATE,'HH24') NOT BETWEEN '9' AND '17' THEN
    RAISE_APPLICATION_ERROR(-20001,'非工作时间');
  END IF;
END;
我首先把系统时间调到了9:00以前,触发器好使;当我把系统时间调回到应该不被触发的正常时间(比如10:00或其他正常时间)的时候,触发器还是被触发,起作用。请问这是什么原因?如何解决这个问题??

解决方案 »

  1.   

    1:表中已经有一条deptno=120的记录了
    2:between '9' and '17'这个条件永远无法满足的,'9'比'17'大
    IF to_char(SYSDATE,'HH24') NOT BETWEEN '9' AND '17' THEN
    改成
    IF to_number(to_char(SYSDATE,'HH24')) NOT BETWEEN 9 AND 17 THEN
      

  2.   

    第2个问题明白了,但是第1个问题没有解决。
    表中确实没有deptno=120的记录,就是不好用
      

  3.   

    第2个问题明白了,但是第1个问题没有解决。
    表中确实没有deptno=120的记录,就是不好用
      

  4.   

    deptno是外键吧,你另外的表有没有这个120的记录
      

  5.   

    我觉得你的触发器应当放在DEPT表上吧?CREATE OR REPLACE TRIGGER tr_update_cascade
    BEFORE UPDATE OF deptno ON --->dept <-----(这里)
    FOR EACH ROW
    BEGIN
      UPDATE emp SET deptno=:new.deptno
      WHERE deptno=:old.deptno
    END;否则第一是逻辑上说不通,按道理应该级联更新的意思是主表更新,从表跟着更新。
    很明显,但DEPT定义表更新后,同时更新雇员EMP表中的DEPTNO字段才对。
    第二是触发器错误,不能在表的行级触发器中对自身做出修改。
      

  6.   

    另外,我没有测试,只是猜测,可能你需要把外键约束删除,级联更新才能起作用。
    这一点希望你能测试下。还有:old和:new为默认绑定变量,是不用定义的。假如你想使用其他的变量来代替
    可以在for each row之前使用
    referencing old as old1,new as new1
    这样你将需要使用:old1.xxxx来表明变量。
    一般来说没有这种必要。
      

  7.   

    同意楼上的,把触发器中的emp改为dept应该就ok了