« トリガーカスケード制限 #1 | トップページ | トリガーカスケード制限 #3 »

2008年9月 5日 (金)

トリガーカスケード制限 #2

さて、前回のつづき。

今回は無限ループする(実際にはしませんけど)させずにトリガーカスケード制現値を確認する。(前回の実験でも十分なんですが。。)

環境は前回と同じです。

シナリオ1

32テーブルに1トリガー/表で32のINSERTトリガーを定義し正しく動作することを確認する。(カスケード制現値が49のようなのでトリガーの32連鎖では問題ないはず!)

33テーブルを作成しておく。

SCOTT> l
1 begin
2 for seq in 1..33 loop
3 execute immediate 'create table t'||to_char(seq,'FM09')|| ' (seq# number)';
4 end loop;
5* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT> select table_name from user_tables where table_name like 'T%' order by table_name;

TABLE_NAME
------------------------------
T01
T02
T03
T04

・・・・中略・・・・

T30
T31
T32
T33

33行が選択されました。

SCOTT>

作成した各表に1つづつ32のトリガーを定義する。
ちなみに、イメージとしては親表にINSERT文が発行されるとトリガーが起動し子表へデータをINSERTする。以下、子表へのINSERT文でトリガーが起動し孫表へINSERT....の繰り返しでトリガーを32回起動させる。

SCOTT> l
1 declare
2 ddlstr constant varchar2(1000)
3 := 'create or replace trigger trg__$$seq$$__'
4 || ' after insert on t__$$seq$$__ '
5 || ' for each row '
6 || 'begin'
7 || ' insert into t__$$nextSeq$$__ values(:new.seq# + 1); '
8 || 'end;';
9 wkstr varchar2(2000);
10 begin
11 for seq in 1..32 loop
12 wkstr := replace(
13 replace(
14 ddlstr,'__$$seq$$__',to_char(seq,'FM09')
15 ),
16 '__$$nextSeq$$__',
17 to_char(seq+1,'FM09')
18 );
19 -- dbms_output.put_line(wkstr);
20 execute immediate wkstr;
21 end loop;
22* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> l
1 select text
2 from all_source
3 where name like 'TRG__'
4 and type = 'TRIGGER'
5* order by name,line
SCOTT> /

TEXT
--------------------------------------------------------------------------------
trigger trg01 after insert on t01 for each row begin insert into t02 values(
:new.seq# + 1); end;

trigger trg02 after insert on t02 for each row begin insert into t03 values(
:new.seq# + 1); end;

trigger trg03 after insert on t03 for each row begin insert into t04 values(
:new.seq# + 1); end;

・・・・中略・・・・

trigger trg30 after insert on t30 for each row begin insert into t31 values(
:new.seq# + 1); end;

trigger trg31 after insert on t31 for each row begin insert into t32 values(
:new.seq# + 1); end;

trigger trg32 after insert on t32 for each row begin insert into t33 values(
:new.seq# + 1); end;


32行が選択されました。

SCOTT>

実行!

SCOTT> insert into t01 values(1);

1行が作成されました。

SCOTT>

正常にINSERTできたようですね。

SCOTT> set serveroutput on size 10000
SCOTT> l
1 declare
2 seq# number;
3 begin
4 for i in 1..33 loop
5 execute immediate 'select * from t'||to_char(i,'fm09') into seq#;
6 dbms_output.put_line('T'||to_char(i,'fm09')||':'||to_char(seq#));
7 end loop;
8* end;
SCOTT> /
T01:1
T02:2
T03:3

・・・・中略・・・・

T31:31
T32:32
T33:33

PL/SQLプロシージャが正常に完了しました。

SCOTT>

シナリオ2

33テーブルに1トリガー/表で33のINSERTトリガーを定義し正しく動作することを確認する。(カスケード制現値が49のようなのでトリガーの33連鎖でも問題ないはず!)


さきほどのデータはじゃまなのでロールバックしておく。

SCOTT> rollback;

ロールバックが完了しました。


テーブルとトリガーを各1つ追加作成し、トリガーを33連鎖させる。

SCOTT> create table t34 as select * from t33;

表が作成されました。

SCOTT> l
1* create or replace trigger trg33 after insert on t33 for each row begin insert into t34 values(:new.seq# + 1); end;
SCOTT>

SCOTT> l
1 select text
2 from all_source
3 where name like 'TRG__'
4 and type = 'TRIGGER'
5* order by name,line
SCOTT> /

TEXT
--------------------------------------------------------------------------------
trigger trg01 after insert on t01 for each row begin insert into t02 values(
:new.seq# + 1); end;

trigger trg02 after insert on t02 for each row begin insert into t03 values(
:new.seq# + 1); end;


・・・・中略・・・・


trigger trg32 after insert on t32 for each row begin insert into t33 values(
:new.seq# + 1); end;

trigger trg33 after insert on t33 for each row begin insert into t34 values(:new
.seq# + 1); end;


33行が選択されました。

SCOTT>


どうなりますか!。実行してみる。

SCOTT> insert into t01 values(1);

1行が作成されました。

SCOTT>

トリガーの33連鎖は無事終了。

SCOTT> l
1 declare
2 seq# number;
3 begin
4 for i in 1..34 loop
5 execute immediate 'select * from t'||to_char(i,'fm09') into seq#;
6 dbms_output.put_line('T'||to_char(i,'fm09')||':'||to_char(seq#));
7 end loop;
8* end;
SCOTT> /
T01:1
T02:2
T03:3

・・・・中略・・・・

T31:31
T32:32
T33:33
T34:34

PL/SQLプロシージャが正常に完了しました。

SCOTT>


シナリオ3

50テーブルに1トリガー/表でINSERTトリガーを定義し正しく動作することを確認する。(カスケード制現値が49のようなのでトリガーの50連鎖ではエラーがになるはず!)

SCOTT> rollback;

ロールバックが完了しました。

SCOTT> l
1 begin
2 for i in 35..52 loop
3 execute immediate 'create table t'||to_char(i,'fm09')|| ' as select * from t34';
4 end loop;
5* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> l
1 declare
2 ddlstr constant varchar2(1000)
3 := 'create or replace trigger trg__$$seq$$__'
4 || ' after insert on t__$$seq$$__ '
5 || ' for each row '
6 || 'begin'
7 || ' insert into t__$$nextSeq$$__ values(:new.seq# + 1); '
8 || 'end;';
9 wkstr varchar2(2000);
10 begin
11 for seq in 34..50 loop
12 wkstr := replace(
13 replace(
14 ddlstr,'__$$seq$$__',to_char(seq,'FM09')
15 ),
16 '__$$nextSeq$$__',
17 to_char(seq+1,'FM09')
18 );
19 -- dbms_output.put_line(wkstr);
20 execute immediate wkstr;
21 end loop;
22* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> l
1 select text
2 from all_source
3 where name like 'TRG__'
4 and type = 'TRIGGER'
5* order by name,line
SCOTT> /

TEXT
--------------------------------------------------------------------------------
trigger trg01 after insert on t01 for each row begin insert into t02 values(
:new.seq# + 1); end;

trigger trg02 after insert on t02 for each row begin insert into t03 values(
:new.seq# + 1); end;

trigger trg03 after insert on t03 for each row begin insert into t04 values(
:new.seq# + 1); end;

・・・・中略・・・・

trigger trg48 after insert on t48 for each row begin insert into t49 values(
:new.seq# + 1); end;

trigger trg49 after insert on t49 for each row begin insert into t50 values(
:new.seq# + 1); end;

trigger trg50 after insert on t50 for each row begin insert into t51 values(
:new.seq# + 1); end;


50行が選択されました。

SCOTT>


では実行!

SCOTT> insert into t01 values(1);
insert into t01 values(1)
*
行1でエラーが発生しました。:
ORA-00036: 再帰的SQLレベルの最大値(50)を超えました ORA-06512:
"SCOTT.TRG50", 行1
ORA-04088: トリガー'SCOTT.TRG50'の実行中にエラーが発生しました ORA-06512:
"SCOTT.TRG49", 行1
ORA-04088: トリガー'SCOTT.TRG49'の実行中にエラーが発生しました ORA-06512:
"SCOTT.TRG48", 行1
ORA-04088: トリガー'SCOTT.TRG48'の実行中にエラーが発生しました ORA-06512:
"SCOTT.TRG47", 行1
ORA-04088: トリガー'SCOTT.TRG47'の実行中にエラーが発生しました ORA-06512:
"SCOTT.TRG46", 行1
ORA-04088: トリガー'SCOTT.TRG46'の実行中にエラーが発生しました ORA-06512:
"SCOTT.TRG45", 行1
ORA-04088: トリガー'SCOTT.TRG45'の実行中にエラーが発生しました ORA-06512:
"SCOTT.TRG44", 行1
ORA-04088: トリガー'SCOTT.TRG44'の実行中にエラーが発生しました ORA-06512:
"SCOTT.TRG43", 行1
ORA-04088: トリガー'SCOTT.TRG43'の実行中にエラーが発生しました ORA-06512:
"SCOTT.TRG42", 行1
ORA-04088: トリガ


SCOTT>

おおお〜〜〜。 :) でましたね。トリガーを50連鎖させたところで制限を超えたようだ。

最後に、トリガーを49連鎖させることが可能なことを確認しておく。

シナリオ4

49テーブルに1トリガー/表で49のINSERTトリガーを定義し正しく動作することを確認する。(カスケード制現値が49のようなのでトリガーの49連鎖は正常に実行できるはず!)

SCOTT> alter trigger trg50 disable;

トリガーが変更されました。

SCOTT>
SCOTT> l
1 select count(src.text)
2 from
3 all_source src join user_triggers trg
4 on src.name = trg.trigger_name
5 where
6 src.name like 'TRG__'
7 and src.type = 'TRIGGER'
8 and trg.status = 'ENABLED'
9 order by
10 src.name,
11* src.line
SCOTT> /

COUNT(SRC.TEXT)
---------------
49

SCOTT>
SCOTT> rollback;

ロールバックが完了しました。

SCOTT> insert into t01 values(1);

1行が作成されました。

SCOTT>

ということで、Linux(32bit)環境ではトリガーカスケード最大値は49ということになる。

Windowsや32bit/64bitで違いはあるのだろうか??? 違いが無かったらマニュアルが間違っているということか?!・・・・・・。別途調査予定。

|

トラックバック


この記事へのトラックバック一覧です: トリガーカスケード制限 #2:

コメント

コメントを書く