Conner McDonaldさんのツイートで、彼が過去に書いた記事の話をしていました。
彼の記事では、以下を推奨しています。
列のデフォルト値の指定にトリガーを使用すると遅くなるので、そのかわりにdefault on nullを使用すべき。
クイックSQLで生成されるSQLを確認してみました。最新版のOracle APEXにバンドルされているクイックSQLは何故か、11g向けのDDLは生成しなくなったので(DBのバージョンに11gを選択しても)、LiveSQLを使って確認します。
確認に使うクイックSQLのモデルは以下です。主キーとして列IDが生成され、それ以外に列MY_DATEを定義しています。この列のデフォルト値はSYSDATEです。
test
my_date date /default sysdate
最初に11g向けのDDLを生成します。
# pk: seq
# db: 11g
test
my_date date /default sysdate
生成されたDDLは以下です。
-- create tables
create table test (
id number not null constraint test_id_pk primary key,
my_date date default SYSDATE
)
;
-- triggers
create sequence test_seq;
create or replace trigger test_biu
before insert or update
on test
for each row
begin
if :new.id is null then
:new.id := test_seq.nextval;
end if;
end test_biu;
/
Conner McDonaldさんの記事では、SELECTの結果を一括して表にロードするINSERT SELECT文の実行により1千万行をトリガーの付いた表にロードすると、トリガーが有効なときは6分37秒かかり、トリガーが無効であれば、4秒弱で終了したという例が示されています。
Oracle Database 11gであれば仕方がないですが、12c以降であればidentityを使いましょう。クイックSQLでDBを12c(またはその上位バージョン)を指定するとデフォルトで主キーの設定にID列が選択されます。
# db: 12c
test
my_date date /default sysdate
生成されるDDLは以下になります。
-- create tables
create table test (
id number generated by default on null as identity
constraint test_id_pk primary key,
my_date date default SYSDATE
)
;
トリガーの定義は無くなりました。
主キーとなる列IDについてはdefault on nullの定義ですが、列MY_DATEのデフォルト設定は、default on nullではなく、単にdefaultです。
動作を確認します。以下のSQL文を実行します。
delete from test;
insert into test(id) values(1);
insert into test(my_date) values(null);
select * from test;
結果は以下になります。値の指定がないときはデフォルト値のSYSDATEが設定されますが、明示的にNULLが指定されているときはNULLになります。
ID | MY_DATE |
---|---|
1 | 13-MAR-21 |
8 | - |
列MY_DATEの定義をDEFAULT ON NULLとなるように変更します。
alter table test modify (my_date default on null sysdate);
同じSQL文を実行します。結果は以下になります。
Result Set 7
ID | MY_DATE |
---|---|
1 | 13-MAR-21 |
9 | 13-MAR-21 |
値としてnullを指定した場合でも、デフォルト値が適用されています。
主キーはさておき、クイックSQLの列ディレクティブで/defaultを指定した場合は、生成されたDDLを確認し、望んでいる動作がdefault on nullであれば、レビュー時にDDLを更新しましょう。
本記事は以上です。
Oracle APEXのアプリケーション開発の一助になれば幸いです。
完