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。在这个触发器中,我使用了三个update语句。。。。他们一直工作到两排,然后。。。。值仅变为null
有人能帮我吗?
此更新语句只能工作到2行。。。。。之后就不起作用了。。。。。我附上了其中一个专栏的屏幕截图。
此处附上第二张图片
为什么使用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
修改同一表的所有行调用触发器,但实际插入的行除外 - todate或to_char过滤器上没有格式验证(如果您实际存储的是日期而不是文本,则不需要进行格式验证(
- 当您可以简单地反转时,您对abs使用了不必要的函数调用两个日期的顺序