【问题标题】:pl/sql trigger error : exact fetch returns more than requested number of rowspl/sql 触发器错误:精确提取返回的行数超过了请求的行数
【发布时间】:2017-07-25 09:54:24
【问题描述】:

我很难理解我的 pl/sql 触发器出了什么问题。 错误是: 错误报告 - SQL 错误:ORA-01422:精确提取返回的行数超过了请求的行数 ORA-06512: 在“SYSTEM.TRG_LATE_RETURN”,第 6 行 ORA-04088: 执行触发器 'SYSTEM.TRG_LATE_RETURN' 期间出错 01422. 00000 - “精确提取返回的行数超过了请求的行数” *原因:exact fetch 中指定的数字小于返回的行数。 *操作:重写查询或更改请求的行数

我的触发器如下:

create or replace trigger trg_late_return
before update of DETAIL_RETURNDATE, DETAIL_DUEDATE on TY_DETAILRENTAL

declare 
  temp_date DATE:= SYSDATE;
  temp_due_date DATE:= SYSDATE;

BEGIN
  select DETAIL_RETURNDATE
  into temp_date
  from TY_DETAILRENTAL;

  select DETAIL_DUEDATE
  into temp_due_date
  from TY_DETAILRENTAL;

  IF temp_date is null
  THEN
    update TY_DETAILRENTAL
    set DETAIL_DAYSLATE=null;
  END IF;

  if temp_date <> null
  THEN
    if temp_date = trunc(temp_due_date) + 1
    then
      update TY_DETAILRENTAL
      set DETAIL_DAYSLATE=0;
    end if;

    if temp_date > trunc(temp_due_date) + 1
    then
      update TY_DETAILRENTAL
      set DETAIL_DAYSLATE = DETAIL_RETURNDATE - DETAIL_DUEDATE;
    end if;  
  end if;

END;
/ 

SQL 和 PL/SQL 的新手,因此我将不胜感激。

【问题讨论】:

  • 我怀疑TY_DETAILRENTAL 正好只有一行,所以你的select . . . into 语句不起作用。

标签: sql oracle plsql


【解决方案1】:

您的查询或更新都没有过滤器(where 子句),因此您正在处理整个表 - 这不是您想要的。您正试图将这些列的 所有 值转换为只能包含单个值的标量变量。

触发器也针对您正在查询和更新的同一个表,这表明您实际上意味着这是(或需要是)行级触发器,而不是语句级触发器。

这意味着您需要在定义中添加for each row,而不是重新查询和更新表,您可以对可用于行级触发器的new 伪记录进行操作。

您也不能使用&lt;&gt; 与null 进行比较;你已经在使用is null,与之相反的是is not null。虽然你也可以在这里使用else

所以这可能就是你想要的:

create or replace trigger trg_late_return
before update of detail_returndate, detail_duedate
on ty_detailrental
for each row
begin
  if :new.detail_returndate is null
  then
    :new.detail_dayslate := null;
  else
    if :new.detail_returndate = trunc(:new.detail_duedate) + 1
    then
      :new.detail_dayslate := 0;
    elsif :new.detail_returndate > trunc(:new.detail_duedate) + 1
    then
      :new.detail_dayslate := :new.detail_returndate - :new.detail_duedate;
    end if;  
  end if;
end;
/

您也可以在比较它们时使用:new 引用更新后的列值,因此您不需要这些值的局部变量副本。 (您也可以使用:old 查看更新前的值,但这里似乎不需要)。

您对new 伪记录所做的更改将在数据库中的实际匹配行最终更新时使用。

Read more about the new/old pseudorecords,还有关于triggers in general

【讨论】:

  • 谢谢!那解决了那个错误。当我尝试更新时仍然遇到问题,但很可能是我做错了什么,将查看这些链接以进一步了解 pl/sql。
  • 您不会从触发器更新表;您改为修改与表列匹配的 :new 伪记录字段。
猜你喜欢
  • 2018-01-15
  • 1970-01-01
  • 1970-01-01
  • 2013-11-15
  • 1970-01-01
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多