DockerでOracle Database XEのCSV取込&dumpの出入力を試してみるよ

おはよう:relaxed:
今日はDockerでOracle DatabaseXEの環境を作ってみるよ。
CSVでのデータ取り込み・dumpの入出力までやってみるよ

##　Oraｃle Database XEとは？
無償の小規模版Oracle Databaseのことだよ。
サポートがない、使用できる機能が限られているなどの制限はありますが、
個人開発の範囲で使用するには十分という印象です。

2021年６月時点の最新バージョンは18cXE　、過去バージョンの11gも使用できるようでしたが、
今回は18cで試してみます。

参考ページ：
https://www.oracle.com/jp/database/technologies/appdev/xe.html
https://docs.oracle.com/cd/E36055_01/server.112/b66471/getstart.htm


##　Dockerで環境づくり
### docker-imageの準備

```terminal
git clone https://github.com/oracle/docker-images
```

Oracleの公式gitより、 imageを作成するのに必要なprojectをcloneします。


### フォルダを確認
docker-images/OracleDatabase/SingleInstance/dockerfiles以下にこのような形で各バージョンのフォルダが用意されています。

![スクリーンショット 2021-06-27 10.32.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/f90a02ce-96b1-451d-8614-4665550e9a56.png)

### Oracle Database Express Edition（XE）のダウンロード
下記ページより、「Oracle Database 18c Express Edition for Linux x64」をダウンロードします。
ダウンロードしたファイルは１で確認した
docker-images/OracleDatabase/SingleInstance/dockerfiles/以下の同じバージョンのフォルダ内(今回は18.4.0）に置きます。

OracleXEのダウンロードページ：https://www.oracle.com/jp/database/technologies/xe-downloads.html


### shを実行してimageファイルを作成
buildContainerImage.sh　を実行します。

引数は以下公式から引用しました。
公式：https://github.com/oracle/docker-images/blob/main/OracleDatabase/SingleInstance/README.md

今回は、version　18.4.0、Express Editionの実行をするので、下記のような引数を使用します。

```terminal:imageの作成
./buildContainerImage.sh -v 18.3.0 -x

//以下、使用方法
 buildContainerImage.sh -v [version] -t [image_name:tag] [-e | -s | -x] [-i] [-o] [container build option]
Parameters:
   -v: 作成するバージョンを指定。下記から指定する。
       11.2.0.2  12.1.0.2  12.2.0.1  18.3.0  18.4.0  19.3.0  
   -t: image_name:tag for the generated docker image
   -e:　'Enterprise Edition'を使う場合に使用
   -s: 'Standard Edition 2'を使う場合に使用
   -x: 'Express Edition'を使う場合に使用
   -i: MD5 checksumsを無視する場合に使用
   -o: containerを作成するときのオプションを付ける場合に使用
 -e, -s, -xはどれか一つだけ選択可能。
```


下記のようなメッセージが表示されて完了。オレンジで囲った部分が、作成されたイメージの名前になります。
![スクリーンショット 2021-06-27 11.27.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/51008e88-7924-4069-9291-945e291ef682.png)
 
ちなみに、-t オプションでimage名をつけると、こんな形で完了します。

```terminal:image名付きimageの作成
./buildContainerImage.sh -v 18.4.0 -t oraclexe18c:1 -x
```

![スクリーンショット 2021-06-27 15.05.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/1572b694-81e4-ba4d-4763-91720f5c4afe.png)


### docker-composeを作成する

```dockerfile:docker-compose.yml
version: "2"
services:
  db:
   image: oracle/database:18.4.0-xe // image名
   container_name: oracle
   shm_size: 1g
   environment:
     - TZ=Asia/Tokyo
     - LANGUAGE=ja_JP.ja
     - NLS_LANG=Japanese_Japan.AL32UTF8 // point1
     - ORACLE_PWD=Oracle18
     - ORACLE_CHARRACTERSET=JA16SJISTILDE // point2
   ports:
     - 1521:1521
     - 5500:5500
     - 8080:8080
   volumes:
     - ./oradata:/opt/oracle/oradata
```

point1: ORACLE_CHARRACTERSET=DB上で扱う文字の設定
point2: NLS_LANGE=メッセージなどの文字表示のデフォルト言語(設定しない場合OS依存になる。）

日本語を扱う場合は上記の設定を入れた方が良いです。
また、別の環境で作成されたdumpデータを取り込む場合などは、設定を同じにしておかないと文字化けの原因になります。

　
できたらコンテナを起動します。

```terminal:dockerコンテナの起動
docker-compose up 
```

このメッセージが出ればOK:relaxed:
![スクリーンショット 2021-07-11 21.15.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/e38336f0-2309-e967-4e68-032fc5f95ad6.png)

コンテナも起動しているのがわかるね。
![スクリーンショット 2021-07-11 21.54.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/59cc1274-e4f8-7dd0-2e6d-d82aa3227684.png)


文字コード参考ページ：
https://www.shift-the-oracle.com/config/multibyte-characterset.html
https://docs.oracle.com/cd/E96517_01/refrn/NLS_LANGUAGE.html#GUID-0DD64F19-BEF2-4B4B-A232-3BA3F8494949



##OracelDBを操作してみよう 
### DBにアクセス

```terminal:dockerのコンテナの中に入る
docker exec -it oracle　/bin/bash

//使用方法
docker exec -it [コンテナ名orコンテナID] /bin/bash
```

```terminal:DBに接続する
sqlplus SYSTEM/Oracle18@//localhost:1521

//使用方法 
sqlplus [ユーザー名]/[パスワード]@//[DB]
```

ユーザー名はDB作成時に作成される管理ユーザーSYSTEMを、
パスワードとDBはdocker-compose.ymlで設定したものを使用します。
![スクリーンショット 2021-07-11 22.09.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/82231b79-cfea-205c-52b0-bfcc84009f90.png)



### TBLを作ってデータを追加
ここでDBを操作してみるよ。
適当なTBLを作って、insertを試してみよう。

```sql
CREATE TABLE koyomi
 (
 id NUMBER(3,0) NOT NULL,
 name VARCHAR2(50),
 year NUMBER(4,0),
 month NUMBER(2,0),
 dates NUMBER(2,0),
 hour NUMBER(2,0),
 minutes NUMBER(2,0),
 PRIMARY KEY(id)
 ) 
;

INSERT INTO koyomi values (1,'七夕',2022,7,7,0,0);
```

こんな感じでINSERTされたことがわかります。
![スクリーンショット 2021-07-11 22.51.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/f6b5aeaf-1d4e-9615-b5d5-0b8aa33ae0cd.png)

デフォルトの表示だとすごく見づらいので、このコマンドで表示幅を調整してあげます。

```sql
set linesize 表示幅;
```
![スクリーンショット 2021-07-11 22.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/15db20b7-8b22-4313-c047-1e426fc516e2.png)
みやすい:relaxed:


### CSVを取り込んでみる。
適当にCSVを作成します。今回はこのような感じ。
docker-compose.ymlにて、ボリュームの設定をしているため、ローカルの./oradata以下にCSVを置くと、
コンテナ内の/opt/oracle/oradata以下にそのファイルがある状態になります。


```import.csv
id,year,month,hour,minutes,name
2,2021,01,05,12,23,小寒
3,2021,01,20,05,40,大寒
4,2021,02,03,23,59,立春
5,2021,02,18,19,44,雨水
6,2021,03,05,17,54,啓蟄
7,2021,03,20,18,37,春分
8,2021,04,04,22,35,清明
9,2021,04,20,05,33,穀雨
(以下続く。合計24行)
```

Oracleにデータを取り込むため　SQL Loaderを使用します。
SQL LoaderはCSVなどの書式が決まったテキストデータを効率よく読み込むのに適しているようです。
使用するためには、コントロールファイルの作成が必要です。今回は下記のようなファイルをｃｓｖと同じ場所に作成しました。
なお、とりあえず取り込めればOKなので、Optionsは適当に最低限しか設定していません。


```import.ctl
OPTIONS(SKIP=1,ERRORS=3000)　//SKIPはテキストデータの読み飛ばす行。ERRORSは許容するエラー数です。
LOAD DATA
INFILE '/opt/oracle/oradata/import.csv'//インポートするファイルの置き場所
APPEND
INTO TABLE koyomi
FIELDS TERMINATED BY ","
(id,year,month,dates,hour,minutes,name)
```

ctlファイルのオプション 参考ページ：
https://docs.oracle.com/cd/E16338_01/server.112/b56303/ldr_params.htm#i1004682


続いて、DBから抜けて、コンテナ上で読み込むためのコマンドを実行します。

```terminal:csvの読込
sqlldr SYSTEM/Oracle18@//localhost:1521 control=/opt/oracle/oradata/import.ctl;

//使用方法
sqlldr ユーザー/パスワード@//DB control=作成したｃｔｌファイルを指定
```

![スクリーンショット 2021-07-12 9.16.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/6b947fad-be4e-7855-a781-45bb9995053b.png)

![スクリーンショット 2021-07-12 9.17.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/3de32e74-4254-e9bd-a810-5cc511fac750.png)

取り込まれていることがわかるね!


### データをdumpしてみる。
今回は一つのテーブルを指定して取り出します。
オプション次第ですべてdumpすることも、スキーマ単位で取ることも可能です。

```
expdp SYSTEM/Oracle18@//localhost:1521 tables="koyomi"

//使用方法
expdp ユーザー/パスワード@//DB tables="エクスポートするテーブル名"
```

オレンジ枠にしたところにdumpファイルが作成されました。
![スクリーンショット 2021-07-17 10.37.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/fbff7ac4-8716-6882-cf8e-3bd2947ffbfd.png)

expdpの参考ページ：https://oracle-chokotto.com/ora_export_expdp.html


###　dumpファイルを取り込んでみる。
出力ができたので、一旦テーブルを消して、取り込みをしたいと思います。
取り込みの準備として、dumpファイルを格納しているディレクトリをOracle上に作ります。

```SQL:テーブルの削除
drop table koyomi;

-- 使用方法
-- drop table テーブル名
```

```SQL:ディレクトリを作成 
create directory my_data_dump as '/opt/oracle/admin/XE/dpdump/';

-- 使用方法
-- create directory 任意のディレクトリ名 as '実際のディレクトリパス'
```

ターミナル上に戻ります。
dumpファイルのファイル権限を変更してから取り込みコマンドを実行します。

```terminal:ファイルの権限変更
chmod 777 /opt/oracle/admin/XE/dpdump/expdat.dmp
```

```terminal:ファイルのimport
impdp SYSTEM/Oracle18@//localhost:1521 directory = my_data_dump dumpfile = "expdat.dmp"

//使用方法
impdp ユーザー名/パスワード@//DB directory =Oracelでつけたディレクトリ名 dumpfile = "expdpで作成されたファイル名"

```

![スクリーンショット 2021-07-18 10.20.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/f77129b2-4797-6821-4dd2-af2eee545a53.png)

完了したね:relaxed:　SELECTもできました:relaxed:


#### ちなみに、impdpの注意点
ファイルの権限をつけていなかったり、directroyの設定をしていないと、
ORA-39001: 引数値が無効です
ORA-39000: ダンプ・ファイル指定が無効です
ORA-39088: ファイル名にパス指定を含めることはできません　
・・・・・他多数なエラーが出ますので、先に設定しおくと良いです。

また、exp/impは古いコマンドで非推奨なので、expdp/impdpを基本は使用するようにしましょう。
ただし、expでエクスポートしたファイルはimpdpでは取り込めないっぽいです。

## 最後に
今回はDockerでOracle環境を作って、いろいろな形式のデータ入出力をためしてみたよ。
Oracleは初めて使ったので、操作感がぎこちないですが、もう少し使いこなせたらいいなあ:relaxed: