Db2:データベースをExportで全部移行してくれ

# Exportの考慮点

このような依頼が来たら、Db2ではどうするでしょうか。単純なテーブルばかりではありません。

- レコード長が32KBを超える
- ラージオブジェクト(LOB)がある
- 自動生成列(GENERATED ALWAYS AS IDENTITY)がある
- トリガー定義がある

考慮することが結構あります。

- 普通にCSVでexportするとレコード長が32KBで切り捨てられる
- CSVはImportするときに改行コードや記号のエスケープを意識しなければいけない
- ラージオブジェクト(LOB)のExportはオプションが必要
- 自動生成列のLoadにはオプション、後処理が必要
- db2moveは自動生成列をサポートしていない
- トリガー定義があるとimport時にトリガーが作動する
- importは処理が遅い

ExportしたファイルをLoadするときの考慮は[次回](https://qiita.com/tsunenorikan/items/e71ff0a8a6c8df9bff7c "Db2:データベースをLoadで全部移行してくれ")の記事もご覧ください。
[Db2:データベースをLoadで全部移行してくれ](https://qiita.com/tsunenorikan/items/e71ff0a8a6c8df9bff7c "次回")

# 前提条件

- サーバー更新に伴い、旧Db2サーバーから新Db2サーバーへのデータ移行
- 旧サーバーと新サーバーでOSとデータベースのバージョンは異なる
- Backup/Restoreを使わず、Exportで移行
- テーブル数は300、5テーブルが1000万レコード以上、20テーブルが100万レコード以上
- アプリケーションのスキーマ名は"DB2ADMIN"

# 環境
Windows Server 2008 → 2016
Db2 Windows V10.1 → V11.5

# Exportするやり方

db2moveは使わず、Exportコマンドを使います。

- Exportする形式はCSV(DEL)ではなくIXF
- ラージオブジェクト(LOB)があるテーブルは"lobfile xxxxxxxx modified by lobsinfile"を追加
- LOBなしとLOBありで処理を分割

#### LOBなしテーブルをExportするSQL

```sql:export_AllTable_without_LOB.ddl
select    current date as date, current time as time    from sysibm.sysdummy1          ;

export to TACCTL.ixf                    of ixf select * from TACCTL                    ;
select    current date as date, current time as time    from sysibm.sysdummy1          ;
export to TADLDT.ixf                    of ixf select * from TADLDT                    ;
select    current date as date, current time as time    from sysibm.sysdummy1          ;
```

コマンドでシステムテーブルからLOBなしテーブルをExportするSQLを生成します。
db2 -txf export_AllTable_without_LOB.gen -z export_AllTable_without_LOB.ddl
<details><summary> LOBなしExportを生成するSQL（左の三角をクリックすると展開）</summary><div>

```sql:export_AllTable_without_LOB.gen
values( 'select    current date as date, current time as time    from sysibm.sysdummy1          ;'   )  ;

select  'export to '
    ||  substr(concat(rtrim(TABNAME),'.ixf                              '),1,29)
    ||  ' of ixf select * from '  
    ||  substr(TABNAME,1,25) 
    ||  ' ;'  
    ||  chr(10)
    ||  'select    current date as date, current time as time    from sysibm.sysdummy1          ;'  
  from SYSCAT.TABLES 
    where not exists ( select * from SYSIBM.SYSCOLUMNS 
                                  where TABNAME = TBNAME
                                    AND coltype IN ( 'BLOB', 'CLOB' ) )
      and TYPE = 'T' 
      and TABSCHEMA = 'DB2ADMIN' 
      and TABNAME not like  ('ADVISE_%')
      and TABNAME not like  ('EXPLAIN_%')
      and TABNAME not in    ('LOCKEVMON','OBJECT_METRICS') 
    order by TABSCHEMA, TABNAME ;
```

</div></details>

#### LOBありテーブルをExportするSQL

```sql:export_AllTable_only_LOB.ddl
select    current date as date, current time as time    from sysibm.sysdummy1          ;

export to TCKPDF.ixf                    of ixf lobfile TCKPDF                    modified by lobsinfile select * from TCKPDF                    ;
select    current date as date, current time as time    from sysibm.sysdummy1          ;
export to TFLDT.ixf                     of ixf lobfile TFLDT                     modified by lobsinfile select * from TFLDT                     ;
select    current date as date, current time as time    from sysibm.sysdummy1          ;
```

"lobfile xxxxxxxx modified by lobsinfile"を追加、LOB出力ファイル名をテーブル名と同じ名前にします(xxxxxxxxはファイル名)。

コマンドでシステムテーブルからLOBありテーブルをExportするSQLを生成します。
db2 -txf export_AllTable_only_LOB.gen -z export_AllTable_only_LOB.ddl
<details><summary> LOBありExportを生成するSQL（左の三角をクリックすると展開）</summary><div>

```sql:export_AllTable_only_LOB.gen
values( 'select    current date as date, current time as time    from sysibm.sysdummy1          ;'   )  ;

select  'export to '
    ||  substr(concat(rtrim(TABNAME),'.ixf                              '),1,29)
    ||  ' of ixf lobfile '  
    ||  substr(TABNAME,1,25) 
    ||  ' modified by lobsinfile select * from '  
    ||  substr(TABNAME,1,25) 
    ||  ' ;'  
    ||  chr(10)
    ||  'select    current date as date, current time as time    from sysibm.sysdummy1          ;'  
  from SYSCAT.TABLES 
    where exists ( select * from SYSIBM.SYSCOLUMNS 
                                  where TABNAME = TBNAME
                                    AND coltype IN ( 'BLOB', 'CLOB' ) )
      and TYPE = 'T' 
      and TABSCHEMA = 'DB2ADMIN' 
      and TABNAME not like  ('ADVISE_%')
      and TABNAME not like  ('EXPLAIN_%')
      and TABNAME not in    ('LOCKEVMON','OBJECT_METRICS') 
    order by TABSCHEMA, TABNAME ;
```
</div></details>

# Exportの実行
コマンドでExportを実行します。
db2- tvf export_AllTable_without_LOB.ddl -z export_AllTable_without_LOB.log
db2 -tvf export_AllTable_only_LOB.ddl -z export_AllTable_only_LOB.log

# 予告
[次回](https://qiita.com/tsunenorikan/items/e71ff0a8a6c8df9bff7c "Db2:データベースをLoadで全部移行してくれ")はExportしたデータをLoadします。
[Db2:データベースをLoadで全部移行してくれ](https://qiita.com/tsunenorikan/items/e71ff0a8a6c8df9bff7c "次回")
よろしくお願いします。