插入触发器后 ORA-01422: 获取 returns 多于请求的行数

After Insert Trigger ORA-01422: fetch returns more than requested number of rows

任何人都可以帮助我使用下面的代码。有 3 个 table:Customer_A1、Reservation_A1 和 Invoice_A1。我正在编写一个触发器,它会在每次进行新预订时执行。

触发器将预加载发票table invoice_id (inv_id), reservation_id (res_id), 客户名字的信息(cust_fname)、客户姓氏 (cust_lname) 和 reservation_start_date。

我的代码如下。创建触发器时没有编译错误。但是,当我向 Reservation table 插入一个新行使触发器执行时,它通知我我的触发器有一个错误

ORA-01422: fetch returns more than requested number of rows.

CREATE OR REPLACE TRIGGER invoice_after_reservation_made
AFTER INSERT
ON RESERVATION_A1
FOR EACH ROW

DECLARE
inv_id INVOICE_A1.INV_ID%type;
res_id INVOICE_A1.res_id%type;
room_id INVOICE_A1.room_id%type;
cust_fname INVOICE_A1.cust_fname%type;
cust_lname INVOICE_A1.cust_lname%type;
reservation_start_date INVOICE_A1.reservation_start_date%type;
cust_id RESERVATION_A1.cust_id%type;

BEGIN
--read reservation_id
res_id:= :new.res_id;
--read room_id
room_id:= :new.room_id;
--read reservation_start_date
reservation_start_date:= :new.reservation_start_date;
--read customer_id
cust_id:= :new.cust_id;
--create new invoice_id
SELECT MAX(INVOICE_A1.inv_id)+1 INTO inv_id FROM INVOICE_A1;

-- import value from CUSTOMER_A1 table to variable cust_fname, cust_lname
Select CUSTOMER_A1.cust_fname,CUSTOMER_A1.cust_lname INTO 
cust_fname,cust_lname 
FROM CUSTOMER_A1 
WHERE CUSTOMER_A1.cust_id=cust_id;

-- Insert record into invoice table
INSERT INTO INVOICE_A1
VALUES (inv_id,res_id,room_id,cust_fname,cust_lname,null,TO_DATE(TO_CHAR(reservation_start_date),'DD/MM/YYYY'),null);


END;

注意:我已经在互联网上查找解决方案,但是没有雪茄。人们说问题主要来自 Select 语句 return 不止一行。但是我的 Select 上面代码中的查询 return 只有一行。我还检查了 table 的数据,在 3 tables Customer_A1、Reservation_A1 和 Invoice_A1 中没有违反实体和参照完整性。我什至将代码复制到一个单独的测试程序中,以便在读取输入后打印出所有变量。测试程序运行良好。我现在投降。请帮我解决这个问题。我是新的 。谢谢

问题出在语句

Select CUSTOMER_A1.cust_fname,CUSTOMER_A1.cust_lname INTO 
cust_fname,cust_lname 
FROM CUSTOMER_A1 
WHERE CUSTOMER_A1.cust_id=cust_id;

您的意思可能是 "Find data from CUSTOMER_A1 where CUSTOMER_A1.cust_id = the value of the variable 'cust_id'"。不幸的是,这不是它的解释方式。数据库将其读取为 "Find data from CUSTOMER_A1 where CUSTOMER_A1.cust_id = CUSTOMER_A1.cust_id" - 换句话说,它将每一行的 CUST_ID 字段与其自身进行比较,发现它们相等(除非是 NULL 值),并且 returns 该行的数据。

写 PL/SQL 时要记住的一个好规则是 "Never give a variable the same name as a column you'll be manipulating"。考虑到这一点,您可以考虑将触发器重写为:

CREATE OR REPLACE TRIGGER invoice_after_reservation_made
  AFTER INSERT
  ON RESERVATION_A1
  FOR EACH ROW
DECLARE
  vInv_id INVOICE_A1.INV_ID%type;
  vRes_id INVOICE_A1.res_id%type;
  vRoom_id INVOICE_A1.room_id%type;
  vCust_fname INVOICE_A1.cust_fname%type;
  vCust_lname INVOICE_A1.cust_lname%type;
  vReservation_start_date INVOICE_A1.reservation_start_date%type;
  vCust_id RESERVATION_A1.cust_id%type;
BEGIN
  --read reservation_id
  vRes_id:= :new.res_id;

  --read room_id
  vRoom_id:= :new.room_id;

  --read reservation_start_date
  vReservation_start_date:= :new.reservation_start_date;

  --read customer_id
  vCust_id:= :new.cust_id;

  --create new invoice_id
  SELECT MAX(INVOICE_A1.inv_id)+1 INTO vInv_id FROM INVOICE_A1;

  -- import value from CUSTOMER_A1 table to variable cust_fname, cust_lname
  Select CUSTOMER_A1.cust_fname,CUSTOMER_A1.cust_lname
    INTO vCust_fname, vCust_lname 
    FROM CUSTOMER_A1 
    WHERE CUSTOMER_A1.cust_id=cust_id;

  -- Insert record into invoice table
  INSERT INTO INVOICE_A1
  VALUES (vInv_id, vRes_id, vRoom_id, vCust_fname, vCust_lname, null, 
          TO_DATE(TO_CHAR(reservation_start_date),'DD/MM/YYYY'), null);
END invoice_after_reservation_made;