2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Oracle Database 23cで追加されたSQLの新機能"DEFAULT ON NULL for UPDATE Statements"をFree版で試してみた

Posted at

23cで追加された"DEFAULT ON NULL for UPDATE Statements"という機能ですが、似たようなものは12cR1からありました。
ただし12cR1で追加されたのはINSERT向けのみで、UPDATEには対応していませんでした。
今回の機能追加でINSERTに加えUPDATEも"DEFAULT ON NULL"が使えるようになっています。
23cマニュアルの新機能一覧の該当箇所はこちら、詳しい説明はこちらで「ON NULL」とページ内検索してください(いずれも英語です)。

テーブル作成

それでは新機能を使ったテーブルを作成していきます。

CREATE TABLE t1 (
    id          NUMBER,
    c1          VARCHAR2(15) DEFAULT 'red',
    c2          VARCHAR2(15) DEFAULT ON NULL FOR INSERT ONLY 'blue',
    c3          VARCHAR2(15) DEFAULT ON NULL FOR INSERT AND UPDATE 'yellow'
);

c1~c3で異なるDEFAULT句を利用していますが、それぞれの内容は以下の通りです。

  • c1:古くからあるDEFAULT句
  • c2:12cR1から使えるINSERT向けのDEFAULT ON NULL句。"FOR INSERT ONLY"という指定は23cで追加されたもの
  • c3:23cで追加されたINSERTおよびUPDATE向けのDEFAULT ON NULL句

ちなみにc2とc3に対しては"DEFAULT ON NULL"句を指定したことで、下記2つの制約が暗黙的に設定されます。

  • NOT NULL
  • NOT DEFERRABLE

INSERTの動作確認

テストデータを挿入しながら、c1~c3の挙動の違いを見てみます。

INSERT INTO t1 (id, c1, c2, c3) VALUES (1, null, null, null);
INSERT INTO t1 (id) VALUES (2);
SELECT * FROM t1 ORDER BY 1;

        ID C1              C2              C3
---------- --------------- --------------- ---------------
         1                 blue            yellow
         2 red             blue            yellow

1行目はすべてnullにしました。
c1はDEFAULT句のみなので空欄に、c2とc3はINSERT向けの"DEFAULT ON NULL"が設定されているため、デフォルト値の"blue"および"yellow"が入っています。
2行目はすべて未指定です。
c2とc3の挙動は1行目と変わりませんが、c1は通常のDEFAULT句で指定された"red"が入っています。

UPDATEの動作確認

先程INSERTしたデータに対してUPDATEをかけていきます。
c1~c3それぞれの挙動を個別に確認します。
まずはc1です。

SQL> UPDATE t1 SET c1 = null;

2行が更新されました。

SQL> SELECT * FROM t1 ORDER BY 1;

        ID C1              C2              C3
---------- --------------- --------------- ---------------
         1                 blue            yellow
         2                 blue            yellow

c1はnull値に対して特に制約もないため、指定した通り空白になりました。
次にc2です。

SQL> UPDATE t1 SET c2 = null;
UPDATE t1 SET c2 = null
              *
1でエラーが発生しました。:
ORA-01407: ("TEST2"."T1"."C2")NULLには更新できません。

c2には12cR1で追加されたINSERT向け"DEFAULT ON NULL"が設定されているため、UPDATEで入力されるnullには有効ではありません。
一方でc2には冒頭で述べたNOT NULL制約、およびNOT DEFERRABLE制約が設定されているため、上記のようにエラーとなります。
次にc3です。

SQL> UPDATE t1 SET c3 = null;

2行が更新されました。

SQL> SELECT * FROM t1 ORDER BY 1;

        ID C1              C2              C3
---------- --------------- --------------- ---------------
         1                 blue            yellow
         2                 blue            yellow

c3はINSERTに加えUPDATEにも"DEFAULT ON NULL"が有効となっているため、エラーとならずDEFAULT値の"yellow"が入力されました。
念のため一度他の値に変更し、再度nullでUPDATEを掛けてみます。

SQL> UPDATE t1 SET c3 = 'white';

2行が更新されました。

SQL> SELECT * FROM t1 ORDER BY 1;

        ID C1              C2              C3
---------- --------------- --------------- ---------------
         1                 blue            white
         2                 blue            white

SQL> UPDATE t1 SET c3 = null;

2行が更新されました。

SQL> SELECT * FROM t1 ORDER BY 1;

        ID C1              C2              C3
---------- --------------- --------------- ---------------
         1                 blue            yellow
         2                 blue            yellow

一度c3に"white"と指定すれば"white"になり、その後"null"を指定すると"DEFAULT ON NULL"で指定した"yellow"に変わりました。

このようにINSERTとUPDATE双方に対応した"DEFAULT ON NULL"ですが、トリガーを使った抜け穴?があります。
以下のようにトリガーを作成すると、c3のデフォルト値をトリガーによって上書き出来てしまいます。
デフォルト値を"null"で上書きした場合、NOT NULL制約に引っかかるためエラーとなります。

SQL> CREATE OR REPLACE TRIGGER t1_t
BEFORE INSERT OR UPDATE ON t1
FOR EACH ROW
BEGIN
  :new.c3 := NULL;
END;
/

トリガーが作成されました。


SQL> INSERT INTO t1 (id, c3) VALUES (3, null);
INSERT INTO t1 (id, c3) VALUES (3, null)
*
1でエラーが発生しました。:
ORA-01400: ("TEST2"."T1"."C3")にはNULLは挿入できません。


SQL> INSERT INTO t1 (id, c3) VALUES (3, 'green');
INSERT INTO t1 (id, c3) VALUES (3, 'green')
*
1でエラーが発生しました。:
ORA-01400: ("TEST2"."T1"."C3")にはNULLは挿入できません。


SQL> INSERT INTO t1 (id) VALUES (3);
INSERT INTO t1 (id) VALUES (3)
*
1でエラーが発生しました。:
ORA-01400: ("TEST2"."T1"."C3")にはNULLは挿入できません。


SQL> UPDATE t1 SET c3 = null;
UPDATE t1 SET c3 = null
              *
1でエラーが発生しました。:
ORA-01407: ("TEST2"."T1"."C3")NULLには更新できません。


SQL> UPDATE t1 SET c3 = 'white';
UPDATE t1 SET c3 = 'white'
              *
1でエラーが発生しました。:
ORA-01407: ("TEST2"."T1"."C3")NULLには更新できません。

このように、どうやってもNOT NULL制約違反となるためエラーが返ってきます。

以上、簡単ですが23cで追加されたSQLの新機能"DEFAULT ON NULL for UPDATE Statements"でした。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?