Oracle - ORA-01422:精确提取返回的行数超过了请求的行数

Posted

技术标签:

【中文标题】Oracle - ORA-01422:精确提取返回的行数超过了请求的行数【英文标题】:Oracle - ORA-01422: exact fetch returns more than requested number of rows 【发布时间】:2011-12-09 15:33:23 【问题描述】:

我仍在为一家小型零售店开发此数据库(谢天谢地,这是一个场景!),目前正在尝试使用触发器解决此问题。

相关实体是客户、付款和订单。付款是其他两者之间的链接实体,因此一个客户可以进行多次付款,而一个订单可能进行多次付款(不寻常但仍然可能),这一切都很好。

触发器:

CREATE OR REPLACE TRIGGER Check_Payment_Status  
BEFORE UPDATE OF Order_Status ON Customer_Order 

for each row
  DECLARE paymentStatus payment.payment_status%type;
  BEGIN

    select payment.payment_status into paymentStatus
    from payment
    where order_no = :new.order_no;

    IF (paymentStatus ='Failed' OR paymentStatus IS NULL ) then  
      RAISE_APPLICATION_ERROR(-20103, 'The full payment has not been made so the order cannot be     processed further until then.');
      update customer_order set order_status='Delayed' where order_no= :new.order_no;
    END IF;

    IF (paymentStatus ='Successful' ) then  
      update payment set payment_date=SYSDATE where order_no= :new.order_no;
    END IF;


  END; 
. 
run

目前还可以。基本上,在将客户的订单标记为“已发货”之前,付款状态必须为“成功”。如果它为空或“失败”,则触发器将类似于“哦,不,你没有!” (但用更正式的话来说)按预期工作。但是,如果有人应用业务规则“一个订单可以有很多付款”,则触发器需要检查所有相关付款,这是我收到此错误的地方,因为 SELECT INTO 语句打算只返回一行。

我已经阅读了一些关于 Cursors 的内容,但我认为我在这里走得太远了 - 请有人提出一些解决方案吗?

【问题讨论】:

如果您只是按照触发器的名称检查付款状态,为什么要在此处更新 payment_date?这似乎不合适 - 您不会在将 payment_status 设置为成功的同一时间点更新付款日期吗? 【参考方案1】:

好吧,如果一个订单可以有多次付款,您如何确定是否全额付款?大概每笔付款都有金额,订单有总金额到期,所以需要检查是否全额支付。在我看来,您可以通过获取所有成功付款的总和然后将其与应付总额进行比较来做到这一点。基本查询是:

  SELECT SUM(payment_amount)
    INTO total_payment_amount
    FROM payment
    WHERE order_no = :new.order_no
      AND payment_status = 'Successful';

【讨论】:

【参考方案2】:

总的来说,您有很多应用程序级逻辑绑定到触发器中,这会给您带来很多麻烦,因为您不知道何时以及为什么更新值您的相关表格。

Dave Costa 对处理付款有一个很好的建议,我会创建一个或多个相关的 PL/SQL 包,其中包含明确编写的函数和过程,用于处理您尝试在此触发器中执行的应用程序级逻辑.

应该很少使用触发器——通常是在您设置序列的主键或审核对表的访问时。

【讨论】:

【参考方案3】:

我知道这是一个老问题,但今天在客户端生产数据库中出现了类似问题。有时按主键(可能是序列号)按降序排序并使用“rownum=1”可能很有用。当然,您应该找出为什么您有多个符合条件的记录,并修复您的应用程序中允许它的错误。

【讨论】:

以上是关于Oracle - ORA-01422:精确提取返回的行数超过了请求的行数的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL ORA-01422:精确提取返回的行数超过了请求的行数

获取 ORA-01422 的原因:精确提取返回的行数超过了请求的行数

WHILE循环出错:ORA-01422:精确提取返回的请求行数多于请求的行数

PL/SQL ORA-01422 SELECT INTO 错误,Oracle 匿名块(NOVA 环境)

ORA-01422:- ORA-06512:

我在编程中不断遇到此问题