ORACLE SQL触发器 - 未找到任何数据

时间:2015-04-04 16:51:41

标签: sql oracle triggers insert

我创建了一个触发器,以便在插入或更新预订记录时,如果评估为0,则会将预订详细信息插入审核表中。如果我更新记录,以下触发器可以正常工作,但在插入时它会给我以下错误:

INSERT INTO "SCOTT"."BOOKING" (PASSENGER_PASSENGER_ID, VOYAGE_VOYAGE_ID, CABIN_NUM, CLASS, EVALUATION) VALUES ('2', '1', '202', 'SECOND', '0')
ORA-01403: no data found
ORA-01403: no data found
ORA-06512: at "SCOTT.EVALUATION_TRIG", line 8
ORA-04088: error during execution of trigger 'SCOTT.EVALUATION_TRIG'
ORA-06512: at line 1


One error saving changes to table "SCOTT"."BOOKING":
Row 2: ORA-01403: no data found
ORA-01403: no data found
ORA-06512: at "SCOTT.EVALUATION_TRIG", line 8
ORA-04088: error during execution of trigger 'SCOTT.EVALUATION_TRIG'
ORA-06512: at line 1

Oracle SQL触发器代码:

create or replace trigger EVALUATION_TRIG
AFTER INSERT OR UPDATE
ON BOOKING 
FOR EACH ROW 
WHEN (NEW.EVALUATION =0)
DECLARE 
PRAGMA AUTONOMOUS_TRANSACTION;
PASSENGER_NAME VARCHAR2(30);
CRUISE_NAME VARCHAR2(30);
VOYAGE_DATE DATE;
SHIP_NAME1 VARCHAR2(30);
BEGIN 
SELECT NAME INTO PASSENGER_NAME FROM PASSENGER JOIN BOOKING
ON PASSENGER.PASSENGER_ID = BOOKING.PASSENGER_PASSENGER_ID
WHERE BOOKING.PASSENGER_PASSENGER_ID = :NEW.PASSENGER_PASSENGER_ID
AND ROWNUM  = 1;
SELECT NAME INTO CRUISE_NAME FROM CRUISE JOIN VOYAGE 
ON CRUISE.CRUISE_ID = VOYAGE.CRUISE_CRUISE_ID 
JOIN BOOKING ON
VOYAGE.VOYAGE_ID = BOOKING.VOYAGE_VOYAGE_ID
WHERE BOOKING.VOYAGE_VOYAGE_ID = :NEW.VOYAGE_VOYAGE_ID
AND ROWNUM= 1;
SELECT START_DATE INTO VOYAGE_DATE FROM VOYAGE JOIN BOOKING
ON VOYAGE.VOYAGE_ID= BOOKING.VOYAGE_VOYAGE_ID
WHERE BOOKING.VOYAGE_VOYAGE_ID = :NEW.VOYAGE_VOYAGE_ID
AND ROWNUM = 1;
SELECT SHIP_NAME INTO SHIP_NAME1 FROM SHIP JOIN VOYAGE 
ON SHIP.SHIP_ID = VOYAGE.SHIP_SHIP_ID JOIN BOOKING 
ON VOYAGE.VOYAGE_ID= BOOKING.VOYAGE_VOYAGE_ID
WHERE BOOKING.VOYAGE_VOYAGE_ID = :NEW.VOYAGE_VOYAGE_ID
AND ROWNUM = 1;
 INSERT INTO EVALUATION_AUDIT VALUES (PASSENGER_NAME, CRUISE_NAME,VOYAGE_DATE, SHIP_NAME1,:NEW.EVALUATION);
 COMMIT;
 END;

1 个答案:

答案 0 :(得分:2)

执行不返回行的select..into语句时会发生该错误,例如触发器中的第一行。

SELECT NAME INTO PASSENGER_NAME FROM PASSENGER JOIN BOOKING
ON PASSENGER.PASSENGER_ID = BOOKING.PASSENGER_PASSENGER_ID
WHERE BOOKING.PASSENGER_PASSENGER_ID = :NEW.PASSENGER_PASSENGER_ID
AND ROWNUM  = 1;

那些:新的值应该用于插入以及更新,但这并不意味着实际数据也存在。

上面的查询在预订时加入了乘客,但是如果您要为该乘客插入第一个预订,则没有当前的预订。此外,要获得乘客的姓名,您根本不需要预订。此外,在同一个表上的行级触发器上查询表X会产生问题。

所以,长话短说,我认为上面的陈述应该是这样的:

SELECT NAME INTO PASSENGER_NAME 
FROM PASSENGER 
WHERE PASSENGER.PASSENGER_ID = :NEW.PASSENGER_PASSENGER_ID;

还需要对其他陈述进行同样的更改。

之后,理论上你仍然可以得到相同的错误,但前提是:NEW.PASSENGER_PASSENGER_ID不匹配任何乘客的id。但在这种情况下,如果您配置了这些约束,我认为您应首先获得外键约束错误。

我还在触发器的末尾看到了一个提交。这也没有多大意义。触发器是语句的一部分,语句本身应该是原子的。从触发器提交,如果这将起作用,将自动提交多行插入中的每一行。 Suggested reading material