-1

table1にトリガーを挿入する前に持っています。一部のデータ (ID) が許可されていない場合、アプリケーション エラーが発生します。

しかし、たとえば、insert into table1 select id from table2 where id in (1,2,3)ID '3' のみが許可されていない場合、他の ID (1 と 2) も挿入されません。

どうすればこれを克服できますか?トリガー コードは次のようになります。

CREATE OR REPLACE TRIGGER t1_before_insert BEFORE INSERT 
ON table1 
FOR EACH ROW 
DECLARE 
xx number(20); 
BEGIN 
select id into xx from blocked_id where id=:new.id; 
if :new.id=xx then raise_application_error(-20001, '--'); 
end if; 
END;
4

2 に答える 2

1

よし、2点。まず、 SELECT INTO ... でNO_DATA_FOUND例外が発生する危険があります。この例外を発生させると、挿入全体が強制終了されます。次に、挿入全体を停止する例外を発生させています。

例外を発生させるのではなく、ブロックされたテーブルにある IDを無視する必要があります。元のアイデアに従うには、 NO_DATA_FOUND 例外を利用して、何も見つからない場合にのみ挿入する方法があります。テーブルにビューを作成し、これにINSTEAD OF トリガーを定義します。

ただし、この方法は使用しません(以下を参照)

テスト環境をセットアップした場合:

SQL> create table tmp_test ( id number );

Table created.

SQL> create table tmp_blocked ( id number );

Table created.

SQL> insert into tmp_blocked values (3);

1 row created.

次に、以下を使用できます。

SQL> create or replace view v_tmp_test as select * from tmp_test;

View created.

SQL> create or replace trigger tr_test
  2   instead of insert on v_tmp_test
  3   for each row
  4
  5  declare
  6
  7     l_id tmp_test.id%type;
  8
  9  begin
 10
 11     select id into l_id
 12       from tmp_blocked
 13      where id = :new.id;
 14
 15  exception when no_data_found then
 16     insert into tmp_test values (:new.id);
 17  end;
 18  /

Trigger created.

SQL> show error
No errors.

SQL>  insert into v_tmp_test
  2   select level
  3     from dual
  4  connect by level <= 3;

3 rows created.

SQL> select * from tmp_test;

        ID
----------
         1
         2

前述のとおり、トリガーは使用しません。より効率的な方法は、 MERGEを使用することです。上記と同じセットアップを使用します。

SQL> merge into tmp_test o
  2  using ( select a.id
  3            from ( select level as id
  4                     from dual
  5                  connect by level <= 3 ) a
  6            left outer join tmp_blocked b
  7              on a.id = b.id
  8           where b.id is null
  9                 ) n
 10     on ( o.id = n.id )
 11   when not matched then
 12    insert values (n.id);

2 rows merged.

SQL>
SQL> select * from tmp_test;

        ID
----------
         1
         2

さらに簡単な方法は、MINUSを使用することです。

 insert into tmp_test
 select level
   from dual
connect by level <= 3
  minus
 select id
   from tmp_banned
于 2013-03-06T11:27:29.813 に答える
0

このようにトリガーとエラーを使用するのは本当に好きではありません。データの整合性は、実際にはトリガーの目的ではありません。これは、おそらくテーブルに挿入するための API として機能するプロシージャで、アプリケーション コードに含める必要があるアプリケーションの一部のように思えます。

于 2013-03-06T11:45:42.100 に答える