0

誰かがこれを手伝ってくれることを願っています。私はトリガーを初めて使用し、変更されているレコードに特定の値があるかどうかを確認するトリガーを作成しようとしています。

たとえば、filing_id とfiling_status を持つ Filing というテーブルがあり、誰かがそのテーブル内の file_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。しかし、チェックする行が複数ある場合 (カウントを行うためだと思います)、2 つのテーブルを使用する必要があります。ここに提案があります。

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 に答える