我是oracle的新手,我正在开发一个医院管理系统,我有这个表来存储患者:
create table patients(
p_id number not null primary key,
p_fullname full_name_ty,
p_gender char,
de_no number,
p_entry date ,
Diagnosis varchar2(25),
p_exit date,
constraint pdf foreign key (de_no) references department(dep_no)
);
其中p_entry是患者进入医院的日期,我做了一个触发器,计算患者(p_exit)日期更新后医院的住院时间(设置此日期表示患者已经离开医院),触发器将简单地计算两个日期之间的差异,并打印出来,这里是触发器的代码:
create or replace
trigger period_trig before update of p_exit on patients for each row
DECLARE
period Number(3);
enterr DATE;
exitt DATE;
BEGIN
enterr := :old.P_ENTRY;
exitt:= :NEW.P_EXIT;
Period :=exitt-enterr;
DBMS_OUTPUT.PUT_LINE('Duration:'||period);
update patients SET RESIDENCY= Period where P_ID = :old.P_ID;
end period_trig
当我测试触发器时使用并使用这样的更新语句:
update patients set p_exit = to_date('01/02/2001','dd/mm/yyyy') where p_id = 2;
并运行它我收到此错误:
Error starting at line 1 in command:
update patients set p_exit = to_date('01/02/2001','dd/mm/yyyy') where p_id = 2
Error report:
SQL Error: ORA-04091: table SEM.PATIENTS is mutating, trigger/function may not see it
ORA-06512: at "SEM.UPDATEPAT", line 5
ORA-06512: at "SEM.PERIOD_TRIG", line 10
ORA-04088: error during execution of trigger 'SEM.PERIOD_TRIG'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
Error starting at line 1 in command:
update patients set p_exit = to_date('01/02/2001','dd/mm/yyyy') where p_id = 2
Error report:
SQL Error: ORA-04091: table SEM.PATIENTS is mutating, trigger/function may not see it
ORA-06512: at "SEM.PERIOD_TRIG", line 11
ORA-04088: error during execution of trigger 'SEM.PERIOD_TRIG'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
谁能告诉我如何修复它?非常感谢..
答案 0 :(得分:1)
您正在修改当前正在修改的触发器中的同一个表。正如他们的错误告诉你的那样:
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
实际上不需要再次更新表,您可以直接在表上使用虚拟列,使整个触发器冗余:
CREATE TABLE patients(
p_id NUMBER NOT NULL PRIMARY KEY,
p_fullname VARCHAR2(255),
p_gender CHAR(1),
de_no NUMBER,
p_entry DATE,
Diagnosis VARCHAR2(25),
p_exit DATE,
RESIDENCY NUMBER GENERATED ALWAYS AS (p_exit-p_entry)
);
insert into patients (p_id, p_fullname, p_gender, de_no, p_entry, diagnosis) values (1, 'GVENZL', 'M', 1234, SYSDATE-1, 'healthy' );
commit;
select p_fullname, residency from patients;
update patients set p_exit = sysdate;
commit;
select p_fullname, residency from patients;