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

Mo *_*osa 1 oracle triggers plsql cursor

我还在为这个小型零售商店(这个场景,谢天谢地!)工作,我正在尝试用触发器解决这个问题.

相关实体是客户,付款和订单.付款是另外两个之间的链接实体,因此一个客户可以进行多笔付款,一个订单可以有多笔付款(不寻常但仍然可能),这一切都很好.

触发:

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
Run Code Online (Sandbox Code Playgroud)

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

我已经阅读了一些游标,但我想我在这里走得太远了 - 请问有人建议一些解决方案吗?

Dav*_*sta 9

那么,如果订单可以有多笔付款,您如何确定是否全额付款?据推测,每笔付款都有一笔金额,订单总金额到期,因此您需要检查是否已支付全部金额.在我看来,你可以通过获得所有成功付款的总和,然后将其与应付总金额进行比较来实现.基本查询将是:

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


fur*_*n87 9

总的来说,你有很多应用程序级逻辑绑定到一个触发器,这会让你遇到很多麻烦,因为你不知道在相关的表中更新值的时间和原因.

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

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