0

希望有人可以帮助解决这个问题。我是触发器的新手,我正在尝试创建一个触发器来检查正在修改的记录是否具有特定值。

例如,我有一个名为 Filing 的表,它有一个 Filing_id 和一个 Filing_status,我想防止有人更新或删除该表中具有 Filing_status="FILED" 的任何记录。所以如果我有以下

Filing_id    Filing_status    Val
---------    -------------    ---
0             Filed           X

如果有人试图修改 Val 触发器应该停止它我创建了以下触发器:

CREATE or replace TRIGGER TRG_PREV_FILING
  BEFORE DELETE or UPDATE
  ON PF.FILING
  FOR EACH ROW
   declare
     rowcnt number;
   BEGIN
     SELECT COUNT(filing_id) INTO rowcnt FROM PF.FILING 
      where status = 'FILED'
       and  filing_id = :new.filing_id;
     if (rowcnt > 0)
     then
      raise_application_error (-20100, 'You can not delete Or Update initial record');
     end if;
   END;

我面临的问题是我得到:ORA-04091 这是“表归档正在变异,触发器/函数可能看不到它”

所以基本上我不能在我正在执行触发器的同一张表上查询?这是我的问题吗?有人知道解决这个问题吗?

我很感激任何帮助

4

2 回答 2

3

您不必查询正在触发的表触发器就可以进行这种检查。您可以使用 获取正在修改的列的值:old。这是一个例子:

SQL> create table filing(
  2    status varchar2(31),
  3    val    number
  4  );

Table created


SQL> create or replace trigger TRG_FILING before delete or update on FILING
  2  for each row
  3  begin
  4    if lower(:old.status) = 'filed'
  5    then
  6      raise_application_error(-20000, 'You cannot delete or modify this record');
  7    end if;
  8  end;

SQL> /

Trigger created


SQL> insert into FILING values('FILED', null);

1 row inserted

SQL> insert into filing values('OK', 1);

1 row inserted

SQL> commit;

Commit complete

SQL> select *
  2    from filing;

STATUS                                 VAL
------------------------------- ----------
FILED                           
OK                                       1 

SQL> delete
  2    from filing
  3   where val is null;


ORA-20000: You cannot delete or modify this record
ORA-06512: at "HR.TRG_FILING", line 4
ORA-04088: error during execution of trigger 'HR.TRG_FILING'
于 2012-10-05T20:43:57.180 回答
0

基本点是您应该以触发器根据更新/删除的行进行验证的方式设计数据库。如果您有几行相同的行,filing_id那么您可能会使您的数据库设计工作过度。也许你真的只检查自己的表,在这种情况下你可以使用:old. 但是当您有几行要检查时(我假设这是因为您进行了计数),那么您必须使用两个表。这是一个建议。

create table filing_status (filing_id number, status varchar2(10));
create table filing_content (filing_id number, content_id number, content varchar2(200));
CREATE or replace TRIGGER TRG_PREV_FILING
  BEFORE DELETE or UPDATE
  ON FILING_content
  FOR EACH ROW
   declare
     rowcnt number;
   BEGIN
     SELECT COUNT(filing_id) INTO rowcnt FROM FILING_status 
      where status = 'FILED'
       and  filing_id = :new.filing_id;
     if (rowcnt > 0)
     then
      raise_application_error (-20100, 'You can not delete Or update filed record');
     end if;
   END;
/
insert into filing_status values (1, 'FILING');
insert into filing_content values (1, 1, 'foo');
insert into filing_content values (1, 2, 'bar');
insert into filing_status values (1, 'FILED');
update filing_content set content = 'bahr' where filing_id = 1 and content_id = 2;

ERROR at line 1:
ORA-20100: You can not delete Or update filed record
ORA-06512: at "DEMO.TRG_PREV_FILING", line 9
ORA-04088: error during execution of trigger 'DEMO.TRG_PREV_FILING'
于 2012-10-05T21:14:46.730 回答