Db2のOracle互換機能を使ってみた😃<1>　～データベースの作成～

#IBM Db2のOracle互換フィーチャー機能 
IBMのDb2は、その振る舞いを他RDBと同様になるように変更したり、他RDBの機能を追加したりすることができます。
DB2_COMPATIBILITY_VECTOR レジストリ変数を設定することによって、他RDB機能互換機能の使用ができるようになりますが、ここではOracle用の互換機能を紹介します。
DB2_COMPATIBILITY_VECTOR レジストリー変数の詳細や、その他のRDB用の設定については、以下の **IBM Db2 V11.5のKnowledge Center**を参照してください。
***<参考資料A>***
**DB2_COMPATIBILITY_VECTOR レジストリー変数**
https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_11.5.0/com.ibm.db2.luw.apdv.porting.doc/doc/r0052867.html

Oracle用の互換モードをすべてONに設定する場合、**DB2_COMPATIBILITY_VECTOR レジストリー変数**に**ORA**を指定します。
NULL（デフォルト）の場合は互換フィーチャーはアクティブになりません。

###Oracle互換機能
「表1.DB2_COMPATIBILITY_VECTORレジストリ変数で設定される機能」を参照してください。
表1は参考資料Aに記載されているものですが、Oracleに関連しない項目は省いて抜粋してあります。
この中の<font color="red">赤字</font>で記載された機能は、データベース作成時に機能が組み込まれるため、データベース作成前にDB2_COMPATIBILITY_VECTORレジストリ変数を設定しておく必要があります。
なお、データベース作成後に変更することはできませんので注意が必要です。
各機能ごとに設定したい場合は、00000000 から FFFFFFFF までの 16 進数で設定します。
複数機能を組み合わせて設定することも可能です。（例は後述）

表1. DB2_COMPATIBILITY_VECTORレジストリ変数で設定される機能（引用元：参考資料A）

|ビット位置| 16進数　　　 |互換フィーチャー|説明  |
|:--------:|:--------------:|:---------------|:-----|
| 1 |0x01|ROWNUM疑似列|このビットは、ROWNUM 疑似列を ROW_NUMBER() OVER() 関数のシノニムとして使用することを可能にし、ROWNUM 疑似列を SQL ステートメントの WHERE 節に含めることを許可します。|
| 2 |0x02|DUAL表|このビットは、DUAL 表への非修飾参照を SYSIBM.DUAL として解決します。|
| 4 |0x08|階層照会 |このビットは、CONNECT BY 節を使用した階層照会のサポートを有効にします。|
| 5 |0x10|<font color="red">NUMBER データ・タイプ ※1</font>|このビットは、NUMBER データ・タイプおよび関連する数値処理のサポートを有効にします。 このサポートを有効にしてデータベースを作成すると、number_compat データベース構成パラメーターは ON に設定されます。|
| 6 |0x20|<font color="red">VARCHAR2 データ・タイプ ※1</font>|このビットは、VARCHAR2 データ・タイプと NVARCHAR2 データ・タイプ、および関連する文字ストリング処理のサポートを有効にします。このサポートを有効にしてデータベースを作成すると、varchar2_compat データベース構成パラメーターは ON に設定されます。|
| 7 |0x40|<font color="red">DATE データ・タイプ ※1</font>|このビットは、DATE データ・タイプを TIMESTAMP(0) データ・タイプとして解釈できるようにし、日付情報だけでなく時刻情報も含まれるようにします。例えば、日付互換モードでは、ステートメント「VALUES CURRENT DATE」は、2016-02-17-10.43.55. のような値を返します。このサポートを有効にしてデータベースを作成すると、date_compat データベース構成パラメーターは ON に設定されます。|
| 8 |0x80|TRUNCATE TABLE |このビットは、TRUNCATE ステートメントの代替セマンティクスを有効にします。IMMEDIATE がオプション・キーワードになり、デフォルトになります。TRUNCATE ステートメントが論理的な作業単位内の最初のステートメントでない場合は、TRUNCATE ステートメントが実行される前に暗黙的なコミット操作が行われます。|
| 9 |0x100|文字リテラル |このビットは、バイト長が 254 以下の文字ストリング定数またはグラフィック・ストリング定数に、VARCHAR または VARGRAPHIC のデータ・タイプでなく、CHAR または GRAPHIC のデータ・タイプを割り当てることができるようにします。|
| 10 |0x200|コレクション・メソッド |このビットは、配列に対して first、last、next、previous などの演算を実行するメソッドを使用できるようにします。 また、この値は、配列内の特定の要素の参照に、大括弧の代わりに小括弧を使用できるようにします。 例えば、array1(i) は array1 の要素 i を参照します。|
| 11 |0x400|<font color="red">Oracle データ・ディクショナリー互換ビュー ※1</font>|このビットは、Oracle データ・ディクショナリー互換ビューの作成を可能にします。|
| 12 |0x800|PL/SQL のコンパイル|このビットは、PL/SQL ステートメントおよび言語要素のコンパイルと実行を可能にします。|
| 17 |0x10000|SQL データ・アクセス・レベルの適用 | このビットは、ルーチンが実行時に SQL データ・アクセス・レベルを適用できるようにします。|
| 18 |0x20000|Oracle データベース・リンク構文 |このビットは、他のデータベース内のオブジェクトにアクセスするための Oracle データベース・リンク構文を有効にします。|
| 19 |0x40000|シノニムの使用 |このビットは、一部の SQL ステートメントでシノニムを使用できないようにします。 シノニムの使用が制限されるよう DB2_COMPATIBILITY_VECTOR レジストリー変数を設定する際は、表のシノニムをターゲットとして指定して alter、drop、rename、truncate の各ステートメントを発行することができません。 ビューのシノニムをターゲットとして指定して alter ステートメントまたは drop ステートメントを発行することもできません。 シーケンスのシノニムをターゲットとして指定して alter ステートメントまたは drop ステートメントを発行することもできません。|
※1：これらのフィーチャーは、データベース作成時のみ適用されます。このフィーチャーを有効または無効にした場合、影響を受けるのは新しく作成されたデータベースのみであり、既存のデータベースは影響を受けません。 

#Oracle互換フィーチャー機能の一般的な使用方法

Oracleの互換機能をすべて有効にする場合、DB2_COMPATIBILITY_VECTOR に ORA を設定します。
設定後、Db2の再起動が必要です。

```
$ db2set DB2_COMPATIBILITY_VECTOR=ORA
```

DB2_COMPATIBILITY_VECTORをORAに設定すると、さらにDB2_DEFERRED_PREPARE_SEMANTICS レジストリー変数のデフォルト値が、'YES' (1 バイト文字セット環境の場合) または 'YES_DBCS_GRAPHIC_TO_CHAR' (2 バイト文字セット環境の場合) のどちらかに変更されます。
ただし、DB2_COMPATIBILITY_VECTORによってDB2_DEFERRED_PREPARE_SEMANTICSが暗黙の値に設定されている場合、その値はdb2setコマンドで照会しても表示されません。（値が設定されていないように見える）
このため、DB2_DEFERRED_PREPARE_SEMANTICSは明示的に設定することをお勧めします。

個別に必要な機能を設定したい場合は、使用したい機能のビットを1とし、ビット演算した値をDB2_COMPATIBILITY_VECTOR に設定します。
詳細は、以下の使用例を参照してください。

###使用例
以下の互換フィーチャーを有効にする例をあげます。

-　ビット5 (0x10): Oracle NUMBER互換
-　ビット6 (0x20): Oracle VARCHAR2互換
-　ビット7 (0x40): Oracle DATE互換
-　ビット11(0x400): Oracleデータ・ディクショナリー互換ビュー

上記を合計すると、0x10 + 0x20 + 0x40 + 0x400 = 0x470 なので、DB2_COMPATIBILITY_VECTORに470をセットします。
ここでは、Db2の再起動後にORADBというサンプルデータベースを作成します。

```
$ db2set DB2_COMPATIBILITY_VECTOR=470
$ db2stop
$ db2start
$ db2sampl -name oradb
```

Oracleデータ・タイプの互換機能がONになっているか確認してみます。

```
$ db2 get db cfg for oradb
……(省略)……
 NUMBER データ・タイプの互換性                           = ON
 VARCHAR2 データ・タイプの互換性                         = ON
 データ・タイプ DATE の TIMESTAMP(0) への互換性          = ON
……(省略)……
```

Oracleデータ・タイプを使用して表T1を作成し、作成した表のデータ・タイプを確認してみます。

```
$ db2 -t
db2 => create table t1 (c1 number, c2 varchar2(10), c3 date);
db2 => describe table t1;

                                データ・タイ データ・           列の       スケ
列名                            プ・スキーマ タイプ名           長さ       ール  NULL
------------------------------- ----------- ------------------- ---------- ----- ------
C1                              SYSIBM      DECFLOAT                     8     0 はい
C2                              SYSIBM      VARCHAR                     10     0 はい
C3                              SYSIBM      TIMESTAMP                    7     0 はい

  3 レコードが選択されました。
```

このように、numberやvarchar2,dateのOracleデータ・タイプは、**Db2データ・タイプに変換され管理**されます。
なお、これらのデータタイプに関しては、関連投稿でも取り上げていますので、参考にしてください。

またこの段階では、**OracleのPL/SQL**は有効にしていないので、以下のようにエラーとなります。

```
$ db2 -td/
db2 => declare
          i number;
       begin
          i := 10;
          dbms_output.put_line('i=' || i);
       end;
       /
DB21034E  コマンドが、有効なコマンド行プロセッサー・コマンドでないため、 SQL
ステートメントとして処理されました。 SQL 処理中に、次のエラーが返されました。
SQL0104N  "BEGIN-OF-STATEMENT" に続いて予期しないトークン "declare i number;
begin i := 10;" が見つかりました。予期されたトークンに "<values>"
が含まれている可能性があります。  LINE NUMBER=1.  SQLSTATE=42601
```

ここで、すべてのOracle互換フィーチャーを有効にしてみます。

```
$ db2set DB2_COMPATIBILITY_VECTOR=ORA
$ db2stop
$ db2start
$ db2 connect to oradb
```

以下のように**Oracle**のPL/SQLが使えるようになりました。

```
$ db2 -td/
db2 => set serveroutput on/
DB20000I  SET SERVEROUTPUT コマンドが正常に完了しました。
db2 => declare
          i number;
       begin
          i := 10;
          dbms_output.put_line('i=' || i);
       end;
       /
DB20000I  SQL コマンドが正常に完了しました。
i=10
```

元々の**DB2**のSQL PLも引き続き使用可能です。

```
db2 => set serveroutput on/
DB20000I  SET SERVEROUTPUT コマンドが正常に完了しました。
db2 => begin
          declare i integer;
          set i = 10;
          call dbms_output.put_line('i=' || i);
       end
       /
DB20000I  SQL コマンドが正常に完了しました。
i=10
```

以上
Oracle互換フィーチャーの概要はここまでです。

では、実際にこの互換機能を使ってみたら、
ということに関しては、関連投稿がありますので、ご参照いただければ幸いです。

##関連投稿
[・Db2のOracle互換機能を使ってみた😃<2>　～可変長列の末尾ブランクの違い～][2]
[2]:https://qiita.com/Seven_Marine/items/f7a31fc71a728282e043

[・Db2のOracle互換機能を使ってみた😃<3>　～空文字(長さ0の文字)の扱い(1)～][3]
[3]:https://qiita.com/Seven_Marine/items/470d58226fe89f017b2a
[・Db2のOracle互換機能を使ってみた😃<4>　～空文字(長さ0の文字)の扱い(2)～][4]
[4]:https://qiita.com/Seven_Marine/items/612e1ca67054337f9758
[・Db2のOracle互換機能を使ってみた😃<5>　～空文字(長さ0の文字)の扱い(3)～][5]
[5]:https://qiita.com/Seven_Marine/items/28c73c824619baf48354
[・Db2のOracle互換機能を使ってみた😃<6>　～空文字(長さ0の文字)の扱い(4)～][6] 
[6]:https://qiita.com/Seven_Marine/items/5cc1afad26ea4eea4644
[・Db2のOracle互換機能を使ってみた😃<7>　～NUMBERタイプの互換性(1)～][7] 
[7]:https://qiita.com/Seven_Marine/items/74bf4af0e65de2222e33
[・Db2のOracle互換機能を使ってみた😃<8>　～NUMBERタイプの互換性(2)～][8]
[8]:https://qiita.com/Seven_Marine/items/a9b2c0e8a03695ef82c1
[・Db2のOracle互換機能を使ってみた😃<9>　～NUMBERタイプの互換性(3)～][9]
[9]:https://qiita.com/Seven_Marine/items/6a47ea5ea6418c6db6e2
[・Db2のOracle互換機能を使ってみた😃<10>　～NUMBERタイプの互換性(4)～][10] 
[10]:https://qiita.com/Seven_Marine/items/b260192afc9ec5c60899


-----
お断り：
当投稿は、Database migration to DB2-IBM Japan Community Wikiに掲載の記事を、Qiita用に書き直したものです。

本資料掲載事項は、ある特定の環境・使用状況においての正確性は確認されていますが、すべての環境において同様の結果が得られる保証はありません。
これらの技術を自身の環境に適用する際には、自己の責任において十分な検証と確認を実施いただくことをお奨めいたします。