Immutable Tableを試す(1)（Oracle Database 19c)

Oracle Database 19cはRelease Update (RU)にバグ・フィックスだけでなく新機能を追加する場合があります。本記事で紹介するImmutable Tableも RU 19.11 で追加された新機能です。Oracle Database 21cの新機能であるBlockchain TableはImmutable Table機能を元に構築されます。

# Immutable Tableとは
Immutable Tableは格納されるレコードの更新や削除を制限し、データの改竄を防ぐ機能を持ったテーブルです。Immutable Tableに対するDROP TABLE文、UPDATE文やDELETE文の実行は指定された期間制限されます。Immutable Tableは通常のテーブル定義に加えて以下の設定を追加することができます。

- テーブル削除を制限する期間
- レコード削除を制限する期間
- レコード削除期間を変更できるか

# 準備
Release Update 19.11をインストールし、データベースに適用します。下記の例ではV$VERSIONビューを確認してRU 19.11が適用されていることを確認しています。

```
SQL> SELECT BANNER_FULL FROM V$VERSION;

BANNER_FULL
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.11.0.0.0
```

次に初期化パラメーターcompatibleを19.11.0.0.0以上に変更する必要があります。

```
SQL> SHOW PARAMETER COMPATIBLE

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
compatible                           string      19.11.0.0.0
noncdb_compatible                    boolean     FALSE
```

設定が漏れている場合、CREATE IMMUTABLE TABLE文の実行がエラーORA-00406で失敗します。

```
SQL> CREATE IMMUTABLE TABLE immutable1 (c1 NUMBER, c2 VARCHAR2(10))
  2    NO DROP UNTIL 1 DAYS IDLE
  3    NO DELETE UNTIL 16 DAYS AFTER INSERT;
CREATE IMMUTABLE TABLE immutable1 (c1 NUMBER, c2 VARCHAR2(10))
*
行1でエラーが発生しました。:
ORA-00406: COMPATIBLEパラメータは、19.11.0.0.0以上必要です。 ORA-00722:
機能"Immutable table"
```

# 作成
Immutable Tableの作成にはCREATE IMMUTABLE TABLE文を実行します。何もオプションを指定しない場合はエラーORA-00905が発生します。

```
SQL> CREATE IMMUTABLE TABLE immutable2(c1 NUMBER, c2 VARCHAR2(10));
CREATE IMMUTABLE TABLE immutable2(c1 NUMBER, c2 VARCHAR2(10))
                                                            *
行1でエラーが発生しました。:
ORA-00905: キーワードがありません。
```

最低限、テーブルの削除制限（NO DROP UNTIL句）と、レコードの削除制限（NO DELETE UNTIL句）を指定します。作成後は通常のテーブルと同様にINSERT文を実行できます。

```
SQL> CREATE IMMUTABLE TABLE immutable1 (c1 NUMBER, c2 VARCHAR2(10))
  2    NO DROP UNTIL 1 DAYS IDLE
  3    NO DELETE UNTIL 16 DAYS AFTER INSERT
  4    TABLESPACE blockts1;

表が作成されました。

SQL> INSERT INTO immutable1 VALUES (100, 'data1');

1行が作成されました。

SQL> COMMIT;

1行が作成されました。
```

上記のCREATE文で作成されたテーブルは USER_TABLESビューだけでなくUSER_IMMUTABLE_TABLESビューに情報が格納されます。

```
SQL> SELECT * FROM user_immutable_tables;

TABLE_NAME                     ROW_RETENTION ROW TABLE_INACTIVITY_RETENTION
------------------------------ ------------- --- --------------------------
IMMUTABLE1                                16 NO  
```

NO DELETE UNTIL句に指定される日数は16日以上を指定する必要があります。

```
SQL> CREATE IMMUTABLE TABLE immutable2(c1 NUMBER, c2 VARCHAR2(10))
  2    NO DROP UNTIL 1 DAYS IDLE
  3    NO DELETE UNTIL 15 DAYS AFTER INSERT;
CREATE IMMUTABLE TABLE immutable2(c1 NUMBER, c2 VARCHAR2(10))
*
行1でエラーが発生しました。:
ORA-05741: minimum retention time too low, should be at least 16 days
```

# 列定義
各レコードの作成日時や制約を実装する情報はORABCTAB_で始まる名前の隠し列として定義されています。しかしUSER_TAB_COLUMNSビューからは参照できません。またSQL*PlusのSET COLINVISIBLE ONを実行しても表示されませんでした。

```
SQL> SET COLINVISIBLE ON
SQL> DESC immutable1
 名前                                    NULL?    型
 ----------------------------------------- -------- ----------------------------
 C1                                                 NUMBER
 C2                                                 VARCHAR2(10)

SQL> SELECT c1, c2, ORABCTAB_SEQ_NUM$ FROM immutable1;

        C1 C2         ORABCTAB_SEQ_NUM$
---------- ---------- -----------------
       100 data1
```