将日期与SQL中的“:new”表进行比较

时间:2012-01-19 17:30:49

标签: sql oracle

我是SQL的初学者,所以请耐心等待。

我正在尝试在SQL中创建一个触发器。这段代码给了我麻烦:

select brw.borage, bt.agelower, bt.ageupper 
into borage, minage, maxage
from borrower brw
  inner join loan ln on ln.borid = brw.borid
  inner join bookcopy bc on ln.bcid = bc.bcid
  inner join booktitle bt on bt.isbn = bc.isbn
where ln.bcid = :new.bcid
and ln.borid = :new.borid;
-- and ln.dateout = :new.dateout;

贷款表中的主键由“bcID”,“borID”和“dateOut”组成。 当我注释掉最后一行时,我将新添加的行添加到表中。 虽然最后一行没有注释,但它不起作用!

我刚收到此错误(取消注释该行):

Row 34: ORA-01403: no data found
ORA-01403: no data found

意味着oracle没有找到符合查询条件的任何行。

注意:当我取消注释该行时,我也会删除其上方的分号。

2 个答案:

答案 0 :(得分:4)

行。首先,表A上的行级触发器不应查询表A。一般来说,这样做会产生一个" ORA-04091:表正在变异"错误。由于您的触发器是在LOAN上定义的,因此查询不应引用LOAN表。它应该只引用:NEW记录中当前行的数据。

既然如此,你可能想要这样的东西(请注意我在这里猜测表之间关系的基数)

select brw.borage
  into borage
  from borrower brw
 where brw.borid = :new.borid;

select bt.agelower, bt.ageupper 
  into minage, maxage
  from bookcopy bc on :new.bcid = bc.bcid
       inner join booktitle bt on bt.isbn = bc.isbn;

你可以将两个查询结合起来,但我没有看到一个简单的方法,而不会使结果比你想要的更复杂。

此外,您确实希望避免使用共享数据库中列的名称的本地变量(如borage)。这往往会产生相当令人费解的范围分辨率错误。例如,使用SCOTT.EMP

没有EMPNO为-17

的员工
SQL> select count(*)
  2    from emp
  3   where empno = -17;

  COUNT(*)
----------
         0

但是当我编写一个简单的PL / SQL块试图计算{-1}}为-17的员工数时,我得到的结果是14.你能发现这个错误吗?

EMPNO

问题在于,当我写SQL> ed Wrote file afiedt.buf 1 declare 2 empno integer := -17; 3 cnt integer; 4 begin 5 select count(*) 6 into cnt 7 from emp e 8 where e.empno = empno; 9 dbms_output.put_line( cnt ); 10* end; SQL> / 14 PL/SQL procedure successfully completed. 时,我明确希望表达式的左侧引用e.empno = empno表和右侧的EMPNO列表达式引用局部变量EMP。不过对我来说不幸的是,Oracle首先将非限定EMPNO解析为表中的一列,然后再解析为同名的局部变量。如果你正在使用命名的PL / SQL块,你可以通过使用块的名称作为局部变量的别名来解决这个问题,但几乎没有人这样做过。

相反,为了避免这些问题,大多数开发人员会为变量名使用某种独特的前缀。例如,我使用EMPNO作为参数名称的前缀,P_作为局部变量的前缀,L_作为包全局变量的前缀。这是一个相对常见的惯例,但存在其他惯例。重要的是要有一些方法来确保你永远不会有一个使用相同名称的局部变量和列名。

答案 1 :(得分:0)

如果您需要忽略此错误并继续执行触发器,则只需添加

即可
exception
  WHEN NO_DATA_FOUND THEN
  NULL

所以触发器的主体看起来像

begin
   select brw.borage, bt.agelower, bt.ageupper 
   into borage, minage, maxage
   from borrower brw
   inner join loan ln on ln.borid = brw.borid
   inner join bookcopy bc on ln.bcid = bc.bcid
   inner join booktitle bt on bt.isbn = bc.isbn
   where ln.bcid = :new.bcid
   and ln.borid = :new.borid;
   and ln.dateout = :new.dateout;
   // other actions

   exception
   WHEN NO_DATA_FOUND THEN
   NULL
end;