Oracle 插入触发器ORA-01422后:fetch返回的行数超过请求的行数
有人能帮我写下面的代码吗。共有3个表:客户表、预订表和发票表。我正在编写一个触发器,它将在每次进行新预订时执行 触发器将预加载发票表中的发票id(库存id)、预订id(库存id)、客户姓名(客户名称)、客户姓氏(客户名称)和预订开始日期信息 我的代码如下。创建触发器时没有编译错误。然而,当我向Reservation表插入一个新行以执行触发器时,它会通知我触发器有一个错误 ORA-01422:fetch返回的行数超过请求的行数Oracle 插入触发器ORA-01422后:fetch返回的行数超过请求的行数,oracle,plsql,sqlplus,database-trigger,Oracle,Plsql,Sqlplus,Database Trigger,有人能帮我写下面的代码吗。共有3个表:客户表、预订表和发票表。我正在编写一个触发器,它将在每次进行新预订时执行 触发器将预加载发票表中的发票id(库存id)、预订id(库存id)、客户姓名(客户名称)、客户姓氏(客户名称)和预订开始日期信息 我的代码如下。创建触发器时没有编译错误。然而,当我向Reservation表插入一个新行以执行触发器时,它会通知我触发器有一个错误 ORA-01422:fetch返回的行数超过请求的行数 注意:我已经在互联网上找到了解决方案,但没有雪茄。人们说问题主要来自返
注意:我已经在互联网上找到了解决方案,但没有雪茄。人们说问题主要来自返回多行的Select语句。但是,上面代码中的Select查询只返回一行。我还检查了表的数据,3个表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;
您的意思可能是“从CUSTOMER_A1查找数据,其中CUSTOMER_A1.cust_id=变量'cust_id'的值”。不幸的是,这不是它的解释。数据库将其读取为“Find data from CUSTOMER_A1 where CUSTOMER_A1.cust_id=CUSTOMER_A1.cust_id”-换句话说,它将每行的cust_id
字段与自身进行比较,发现它们相等(空值除外),并从该行返回数据
编写PL/SQL时要记住的一条好规则是“永远不要给变量指定与要操作的列相同的名称”。考虑到这一点,你可能会考虑将你的触发器重写为:
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;
非常感谢。那是个愚蠢的错误。我把它修好了。一点也不傻-你只是没看到它和电脑一样。:-)顺便说一下,不需要将
:新的值复制到局部变量中。您可以直接使用:new.res\u id
等并保存十几行代码。(或者,如果您确实需要局部变量,您可以将它们的值作为声明的一部分进行赋值,并且仍然可以保存六行代码。)此外,从发票中选择MAX(INVOICE_A1.inv_id)+1到inv_id
将为同时运行它的两个会话提供相同的结果。
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;