sql - ORACLE SQL 触发器 - 未找到数据

标签 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;

最佳答案

当您执行不返回行(例如触发器中的第一行)的 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;

这些 :new 值应该在插入和更新时填写,但这并不意味着实际数据也存在。

上面的查询将乘客加入预订,但如果您要插入该乘客的第一个预订,则没有当前预订。此外,要获取乘客的姓名,您根本不需要预订。此外,在同一个表的行级触发器中查询表 X 可能会出现问题。

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

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

其他语句也需要进行相同的更改。

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

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

关于sql - ORACLE SQL 触发器 - 未找到数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29449003/

相关文章:

MySQL 查询失败

c# - 在查询中使用文本值

oracle - 物化 View : how can I find the number of updates, 在刷新期间插入和删除?

mysql - 为什么在oracle中引入散列分区?有什么好处

Oracle 复合触发器 - 如何存储和 "use"删除的行?索引表?

mysql - 使用 SQL 计算平面表中事件之间的平均时间

SQL通过加入父记录来合并子记录

oracle - Perl install_driver(Oracle) 失败: - 无法为模块 DBD::Oracle Win64 加载 '../DBD/Oracle/Oracle.dll'

mysql - 多个MySQL操作对表交互

mysql - 根据mysql中的时间创建自动更新行