サーバーJava入門先頭  H2 DB編先頭
2007-12-15作成

 ■H2 DB 操作3

 ここではH2 Database Engineで作成した、テーブル操作、データ操作について説明します。

 新規データベースの作成もしくは既存データベースに接続済で、H2 Consoleが開かれているところから話を進めます(データベース作成や接続は、H2 DBの操作2 を参照)。

 このH2 Consoleの画面から、
・テーブルの操作(作成、変更、削除)
・データの操作(追加、参照、更新、削除)
・ユーザーIDの管理(作成、削除、権限の付与、剥奪))
・データベースのバックアップ・リストア
といった、SQLの実行やコマンドの実行を行います。

 テキストボックスにSQLやコマンドを入力し、上部の「実行(Ctrl+Enter)」ボタンを押すか、そのボタンに書いてあるように Ctrl+Enter キー押下でそのSQLやコマンドが実行されます。
 結果はテキストボックスの下に表示されます。

 しかしこのような対話モードだけでは、実行したコマンドを再実行するのみ不便です(テーブルを修正して際CREATEしたい場合、UPDATEを条件や値を変えて何度も行う場合など)。H2 Consoleからデータベースへ接続中で、そのセッション内であればコマンドヒストリを表示して、再実行や一部修正しての実行もできますが、セッションを閉じてしまえばヒストリは消えます。

 そこでSQLスクリプトを事前にテキストファイルで作成しておき、これを実行する方法を次に説明します。

 ■SQLスクリプトの実行

 ■SQLスクリプト

 まずは実行したいSQLやコマンドを、メモ帳やテキストエディタ等でテキストファイルに作成しておきます。
 作成するファイル名は任意です。拡張子部分も通常のテキストファイルである .txt で構いません。ですがここではSQLスクリプトであることを明示するため、 .sql で作成するものとして説明します。つまり SQLスクリプトファイル.sql という形式です。

 このスクリプトを実行するには RUNSCRIPT コマンドを使います。一番簡単な記述方法は

RUNSCRIPT FROM 'SQLスクリプトファイル.sql';

です(SQLスクリプトファイル.sql は、フルパスで指定してください)。
 なお以下に説明するものも含め、コマンド名の大文字小文字は区別されません。なので runscript from ・・・; と記述しても大丈夫です。このページ内では全て大文字で記述します。

 各スクリプトファイル内には複数のSQLやコマンドを記述できます。例えばCREATE TABLEと、そのTABLEに対するCREATE INDEXを1ファイルにしたりと。SQLの終端文字は ; ですので、複数記述するときはそれぞれを ; で区切るのを、くれぐれも忘れずに。

 ■データのLOADとUNLOAD

 ここではH2 DBに対するデータのロードとアンロードについて説明します。
 H2 DBにはロードやアンロードに直接該当するコマンドはありません。代替手段として CSVREADCSVWRITEという関数が用意されているので、これを利用します。

 ・テキストファイルからのLOAD

 最初にCSVファイルの内容を表示するコマンドを実行してみましょう。
 なんでもよいのでCSV形式(複数のデータを、 , で区切ったもの)のテキストファイルを用意してください。仮にファイル名を C:\WORK\DATA\testdata.csv にしたものとします。

 そうしたらH2 Console画面のテキストボックスに、次のように入力し実行してください。

SELECT * FROM CSVREAD('C:\WORK\DATA\testdata.csv');

 実行結果として、testdata.csvの内容が表示されます。

 例として、次の内容の testdata.csv を作成し、実行した結果を載せておきます。

@,A,01,'01'
A,B,02,'02'
B,C,03,"03"
C,D,04,'04'
サンプルCSVデータ


CSVREADサンプルの実行結果
CSVREADサンプルの実行結果

 この実行結果で注意がいるのが、結果表示の下に 3行、10ms と表示されている点です。サンプルCSVデータは4行あるのに、3行と表示されています。結果表示部分は4行表示されているように見えますが、先頭行は色が変わっています。

 これは CSVREAD の仕様のためです。先ほどの CSVREAD の最も単純な書き方、 CSVREAD('対象ファイル名') では、ファイルの先頭行は項目名と解釈されるのです。そのため一見データにしか見えない、例えば"@"もそういう項目名と解釈されているのです。

 もう一点の注意点が、データと解釈された結果の2行目、B,C,03,03の行とその他の行の違いです。2行目は最後の項目に対し、データを " で囲んでいます。その他の行は ' で囲んでいます。
 2行目は " で囲まれた中の 03 だけがデータと認識されていますが、その他の行は ' 自体もデータと解釈されてしまっています。つまりもしも文字列を囲むときは(例えばデータ中に , 自体を含むなど)、デフォルトでは " で囲む必要がある、ということです。

 これらについては次に、 CSVREAD の詳細な記述方法を説明するので、これを参照してください。

 ・CSVREADの詳細

CSVREAD使用方法
コマンド名 説明
CSVREAD CSVREAD (入力テキストファイル名, データ項目名, 文字コード, 項目区切り文字, 引用符文字, エスケープ文字)
入力テキストファイル名 入力するテキストファイルの名称。フルパスで指定する。
 データ項目名 区切り文字で区切られた項目に対する項目名を、カンマ区切りの文字列で指定する。
 ここに null を指定した場合(もしくは無指定の場合)、テキストファイルの先頭行は項目名と見なされる。
文字コード *1 指定したテキストファイルの、文字コードを指定する。
 ここに null を指定した場合(もしくは無指定の場合)、システムのデフォルト文字コードが使用される(Windows環境ならWindows-31J)。
 通常は指定しなくても問題無いと思う。Unixから連動したデータなどのとき、EUC-JPやJISを指定する必要がある。 *2
項目区切り文字 項目区切りに使用する文字列を指定する。
 ここに null を指定した場合(もしくは無指定の場合)、,が区切り文字として使用される。
引用符文字 文字列を表すのに使う、引用符を指定する。項目区切り文字として使用する文字自体がデータに含まれる場合などのときに指定する。
 ここに null を指定した場合(もしくは無指定の場合)、" が引用符として使用される。
エスケープ文字 エスケープ文字を指定する。テキストファイル中に文字列項目があり、そこに引用符文字自体がデータとして含まれるときに使用する。
 例えば yok's というデータ値があり、引用符文字に ' を指定したときを例にする。
 データ中の ' は引用符文字とかぶってしまっている。これを回避する一つの方法としては、データ中の該当文字を連続させれば良い。具体的には例の場合、 yok''s とテキストファイル中に記述しておく。
 もう一つがこのエスケープ文字を指定する方法である。エスケープ文字に \ を指定した場合、先ほどの yok's という文字列はテキストファイルでは、エスケープ文字を使用して yok\'s と記述しておく。

*1) 文字コードは結構奥が深いです。unicodeと言ってもUTF-8やUTF-16の違い、さらにShift-JISとWindows-31Jの違いなど。本当は文字コード無指定のときに文字化けしそうな字などをテストしてみたかったのですが、そこまで手が回りませんでした。

*2) JISと一言で言っても、いろいろな規格があるのですが・・・

 ここで「項目区切り文字を指定できる」のがポイントです。例えば項目区切り文字に char 関数を使って char(9) と指定すると、入力テキストファイルとしてTAB区切りのファイルが使えます(TABを表すASCIIコードは9なので、この値を char 関数の引数に指定します)。関数の名前はCSVREADですが、任意の区切り文字が使える、ということです。

 上記を踏まえて上で例示した「サンプルCSVデータ」を、次の CSVREAD 関数で処理した結果を示します。

SELECT * FROM CSVREAD('C:\WORK\DATA\testdata.csv', 'A,B,C,D', null, null, '''');

 データ項目名としてA、B、C、Dを指定しました。データ項目名の並びを、カンマ区切り文字列として指定します。そのためデータ項目名の並び全体を、SQLの引用符である ' で囲む点を注意してください。
 文字コード、区切り文字は無指定なので、デフォルト値が使われます。
 引用符には ' を指定しました(指定のとき引用符に指定する '' で囲むため、エスケープさせるために ' を連続させています)。
 エスケープ文字は無指定です。

CSVREADサンプルの実行結果2
CSVREADサンプルの実行結果2

 今度は先ほどの例とは違い、全ての行がデータとして扱われています。また引用符に ' を指定したので、今度は3行目は " もデータとして解釈されていますが、その他の行は ' はデータと解釈されていません。

 ・テーブルへのLOAD

 これまで説明したように CSVREAD は基本的に、SELECT文と組み合わせて使います。従ってこれにさらにINSERT文を組み合わせることによって、テキストファイルの内容をH2 DBのTABLEにLOADすることが出来ます。

 例ではtestdata.csvという名前のテキストファイルで説明してきました。
 これに対応した、testdataというTABLEがH2 DB上にCREATE済と仮定します。そうするとテキストファイルからLOADするSQLは、簡単な記述法だと

INSERT INTO TESTDATA
    SELECT * FROM CSVREAD('C:\WORK\DATA\testdata.csv');

や、詳しい指定をした

INSERT INTO TESTDATA
    SELECT * FROM CSVREAD('C:\WORK\DATA\testdata.csv', 'A,B,C,D', null, null, '''');

となります。
 なおデータ項目名はテキストファイル中に含むか、もしくはCSVREAD中に指定します。このデータ項目名と、INSERT先のTABLEに定義されているカラム名は同じである必要はありません。例示した記述方法では、単純にファイル中のデータ形式と、TABLE定義のカラムデータ形式が一致していればINSERTされます。

 ・テキストファイルへのUNLOAD

 次はテーブルの内容をテキストファイルに出力(UNLOAD)する、 CSVWRITE 関数について説明します。

 CSVREAD関数のときは、それをSELECT文に埋め込む形で使用しました(さらにそのSELECT文をINSERT文に埋め込んで使ったり)。
  CSWRITE 関数の場合、H2 Consoleから単独で使用します。関数呼び出し命令のCALL 文を使い、 CALL CSVWRITE・・・ と記述します。

 少し上の「・テーブルへのLOAD」で説明したときの、testdataというTABLEを前提に、これをテキストファイルにUNLOADする方法で説明していきます。

 もっとも簡単な指定方法ですが、H2 Console画面のテキストボックスに、次のように入力し実行してください。

CALL CSVWRITE('C:\WORK\DATA\testdata.csv'), 'SELECT * FROM TESTDATA');

 実行結果として、C:\WORK\DATAに、testdata.csvというCSV形式のテキストファイルが作成されます。

CSWRITE 関数の第一引数で出力先ファイル名(フルパス指定)、第二引数で対象TABLEからのクエリーを記述します。
 例では testdataテーブルの全データ、全項目を出力しました。第二引数にクエリーとしてSELECT文を書くので、対象データを条件で絞り込んだり、特定項目だけを出力するような指定もできます。

 それでは次に、 CSVWRITE の詳細な記述方法を説明します。指定内容は CSVREAD のときとほぼ同じです。

 ・CSVWRITEの詳細

CSVWRITE使用方法
コマンド名 説明
CSVWRITE CSVWRITE (出力テキストファイル名, 出力対象クエリー, 文字コード, 項目区切り文字, 引用符文字, エスケープ文字)
出力テキストファイル名 出力先テキストファイルの名称。フルパスで指定する。
 出力ファイル中の先頭行はデータでなく、出力対象クエリーで指定した結果データの項目名(カラム名)が入る。
 出力対象クエリー ここで指定したクエリーの結果が、テキストファイルとして出力される。
 最も単純な指定内容は 'SELECT * FROM 対象テーブル名' である。この場合は対象テーブルの項目名(カラム名)が、出力テキストファイルの先頭行として出力される。
文字コード *1 指定したテキストファイルに出力するときの、文字コードを指定する。
 ここに null を指定した場合(もしくは無指定の場合)、システムのデフォルト文字コードが使用される(Windows環境ならWindows-31J)。
 通常は指定しなくても問題無いと思う。出力ファイルを別システム、例えばUnixに連動する場合などのとき、EUC-JPやJISを指定する必要がある。
項目区切り文字 項目区切りに使用する文字列を指定する。
 ここに null を指定した場合(もしくは無指定の場合)、,が区切り文字として使用される。
引用符文字 文字列を表すのに使う、引用符を指定する。項目区切り文字として使用する文字自体がデータに含まれる場合などに指定する。
 ここに null を指定した場合(もしくは無指定の場合)、" が引用符として使用される。
エスケープ文字 エスケープ文字を指定する。出力データ項目に文字列項目があり、そこに引用符文字自体がデータとして含まれるときに使用する。
 例えば yok's というデータ値があり、引用符文字に ' を指定したときを例にする。
 データ中の ' は引用符文字とかぶってしまっている。これを回避する一つの方法としては、データ中の該当文字を連続させる方法がある。具体的には例の場合でエスケープ文字が無指定のとき、テキストファイル中には yok''s と出力される。
 もう一つがこのエスケープ文字を指定する方法である。エスケープ文字に \ を指定した場合、先ほどの yok's という文字列はテキストファイルには、エスケープ文字を使用して yok\'s と出力される。

 第2引数の「出力対象クエリー」の意味を考えてもらうと気付くかと思いますが、CSVWRITE は実は、テーブルの内容をテキストファイルに出力するのではないのです。正確にはクエリーの結果をテキストファイルに出力するのです。

 ということでクエリーの内容次第で、
・対象データを条件で絞る
・対象データを並べ替えておく
・複数のテーブルを結合(JOIN)させる
・複数のテーブルを連結(UNION)させる
といったことを行い、その結果をテキストファイルに出力できます。

 またCSVREADと同様にCSVWRITEも、「項目区切り文字」を指定できます。そこで例えば項目区切り文字に char 関数を使って char(9) と指定すると、結果の出力テキストファイルはTAB区切りのファイルとして出力されます(TABを表すASCIIコードは9なので、この値を char 関数の引数に指定します)。関数の名前はCSVWRITEですが、任意の区切り文字で出力出来る、ということです。




このページの先頭  技術メモ先頭  サーバーJava入門先頭  H2 DB Engine編先頭
Copyright © 2007 YOK. All Rights Reserved.