触发器中的 ORACLE SQL 更新语句在 2 行后不起作用

Posted

技术标签:

【中文标题】触发器中的 ORACLE SQL 更新语句在 2 行后不起作用【英文标题】:ORACLE SQL UPDATE STATEMENT IN TRIGGER NOT WORKING AFTER 2 ROWS 【发布时间】:2021-04-30 06:51:03 【问题描述】:
CREATE OR REPLACE TRIGGER BILL_TRG
BEFORE INSERT ON bill
FOR EACH ROW 
DECLARE
d_id VARCHAR2(20);
doc_id VARCHAR2(20);
R_ID VARCHAR2(20);
p_name varchar2(20);

BEGIN
IF :NEW.BILL_NO IS NULL THEN
     SELECT BILL_NO_SEQ.NEXTVAL INTO :NEW.BILL_NO FROM DUAL;
END IF;
IF :NEW.BILL_DATE IS NULL THEN
       UPDATE BILL set BILL_DATE=TO_CHAR(SYSDATE); 
END IF;
IF :NEW.p_name IS NULL THEN
     SELECT p_name INTO :NEW.P_NAME FROM PATIENT WHERE P_ID=:NEW.P_ID;
END IF;
IF :NEW.P_GENDER IS NULL THEN
     SELECT P_GENDER INTO :NEW.P_GENDER FROM PATIENT WHERE P_ID=:NEW.P_ID;
END IF;
IF :NEW.P_ADDRESS IS NULL THEN
     SELECT P_ADDRESS INTO :NEW.P_ADDRESS FROM PATIENT WHERE P_ID=:NEW.P_ID;
END IF;
IF :NEW.D_NAME IS NULL THEN
     SELECT D_ID INTO DOC_ID FROM PATIENT WHERE P_ID=:NEW.P_ID;
     SELECT D_NAME INTO :NEW.D_NAME FROM DOCTOR WHERE D_ID = DOC_ID;
END IF;
IF :NEW.DATE_ADMISSION IS NULL THEN
     SELECT DATE_ADMISSION INTO :NEW.DATE_ADMISSION FROM PATIENT WHERE P_ID=:NEW.P_ID;
END IF;
IF :NEW.days_admitted IS NULL THEN
    UPDATE BILL SET DAYS_ADMITTED=abs(to_date(date_admission)-to_date(date_discharge));
END IF;
IF :NEW.room_charges IS NULL THEN
      SELECT room_id INTO R_ID FROM PATIENT WHERE P_ID=:NEW.P_ID;
      SELECT room_charges INTO :NEW.room_charges FROM room WHERE room_id=R_ID;
      UPDATE BILL SET ROOM_CHARGES=ROOM_CHARGES*DAYS_ADMITTED;
END IF;
IF :NEW.total_amount IS NULL THEN
    UPDATE BILL SET TOTAL_AMOUNT=ROOM_CHARGES+PATHOLOGY_FEES+D_FEES+MISCELLANEOUS;
END IF;
END;
/

首先,我使用的是 Oracle SQL Developer。 在此触发器中,我使用了三个更新语句....它们工作正常,直到两行,之后....值变为 null。

谁能帮我解决这个问题?

This update statement is working till 2 rows only.....after that it is not working.....I am attaching a screenshot of one of the columns.

Attaching 2nd picture here

【问题讨论】:

你能展示一些表格中的示例数据吗? 我已经上传了2张图片......请检查一下。 我只是想问......为什么在触发器中使用更新语句,第三条记录不可见。 请解释一下代码应该做什么。我没有投反对票。但是您可能会惊讶地发现,非工作代码通常不能很好地提供代码intent的上下文和解释。 【参考方案1】:

为什么使用update 而不是直接赋值?您无法更新尚未插入的行,因此您输入的最后一行将始终不正确,并且您将无缘无故更新表中的所有其他行。

总体而言,您的代码和数据模型似乎存在一些重大问题:

    您正在将日期存储为文本 当直接分配(例如NEW.BILL_NO := NVL(:NEW.BILL_NO,BILL_NO_SEQ.NEXTVAL);)可以工作时,您使用select into 您应该避免使用 SQL 连接 减少 SQL 执行次数(例如SELECT D_NAME INTO :NEW.D_NAME FROM DOCTOR D, PATIENT P WHERE D.D_ID = P.D_ID AND P.P_ID = :NEW.P_ID;) 您正在使用update 修改同一个表的所有行 调用触发器除了实际插入的行 to_date 或 to_char 过滤器没有格式验证(如果您实际存储日期而不是文本,则不需要) 当您可以简单地反转时,您对 abs 使用了 不必要的函数调用 两个日期的顺序

【讨论】:

以上是关于触发器中的 ORACLE SQL 更新语句在 2 行后不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何调整oracle中的sql语句输入的最大长度

当我调用触发器更新 STUDENT 表中的总数时,Oracle 中的 SQL 出错

如果触发器中的语句不起作用 SQL(Oracle)

Oracle中的触发器是请求的一部分吗?

oracle update语句怎么写

oracle update触发器如何获取被修改的字段