ワダです。4度目の投稿です。
■DBMSのメタ情報とは
DBMSにおいてメタ情報とは、次のようなものを意味します。
- データベースに存在するテーブルの一覧
- テーブル内のカラムの一覧、キー情報
- カラムの説明、データタイプ、長さ、nullが許されるか、デフォルト値など
古いJDBCドライバではAPIはなく、メタ情報を取得するには各DBMSのデータベースカタログを検索するSQLを投げる必要がありました。
最近JDBCドライバでは、JDBCのAPIを使ってDBMSのメタ情報を取得することができます。
工夫次第で、あらゆるDBMSに対応したプログラムを作成することができそうです。
今回はPostgreSQL、Oracle、SQLServerの3種類で、メタ情報の取得を試してみました。
- API DatabaseMetaData
https://docs.oracle.com/javase/jp/6/api/java/sql/DatabaseMetaData.html - API ResultSetMetaData
https://docs.oracle.com/javase/jp/6/api/java/sql/ResultSetMetaData.html -
お世話になったサイト
http://www.ne.jp/asahi/hishidama/home/tech/java/jdbc_meta.html
■試した環境
今回はこちらの環境で行いました。
Java
- バージョン 8 Update 201
OS
- Windows10 Pro ビルド番号 1803
DBMS
- PostgreSQL
- バージョン: 9.6
- ドライバ:PostgreSQL JDBC 4.2 Driver, 42.2.5(下記からダウンロード)
https://jdbc.postgresql.org/download.html - DB情報と定義
- DB名:sample
- ユーザ名:postgres
- スキーマ、テーブル:public.TEST0001、public.test0002、sch1.TEST0001
- Oracle
- バージョン:12.2.0
- ドライバ:Oracle Database 12c Release 1 (12.1.0.2) drivers(下記からダウンロード)
https://www.oracle.com/technetwork/jp/database/features/jdbc/index-099275-ja.html - DB情報と定義
- DB名:PDB2
- ユーザ名:testuser01
- スキーマ、テーブル:testuser01.TEST0001、testuser01.TEST0002
- SQLServer
- バージョン:SQL Server 2012 Express Edition
- ドライバ:Microsoft JDBC Driver 4.2 for SQL Server(下記からダウンロード)
https://www.microsoft.com/ja-jp/download/details.aspx?id=11774 - DB情報と定義
- DB名:test
- ユーザ名:test01
- スキーマ、テーブル:dbo.TEST0001、sch1.TEST0001
■サンプルプログラム
(相変わらずシンプルなものになりますが)以下のようなサンプルを作成しました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
import java.sql.*;
class MetaTest {
public static void main(String[] args) {
ResultSet rs =null;
ResultSetMetaData metaData=null;
String url = "jdbc:postgresql://localhost:5432/sample";//PostgreSQLの接続文字列
String user = "postgres";//DBユーザ
String password = "1234";//パスワード
String schem = "public";//スキーマ
String table = "TEST0001"; //メタ情報を取得したいテーブル
try {
// データベースとの接続
Connection con = DriverManager.getConnection(url, user, password);
//データベースメタデータの取得
DatabaseMetaData dbmd = con.getMetaData();
System.out.println("-----DatabaseMetaDataの情報-----");
System.out.println("dbmd:driver version = " + dbmd.getDriverVersion());//ドライバのバージョン
System.out.println("dbmd:driver name = " + dbmd.getDriverName());//ドライバ名
System.out.println("db name = " + dbmd.getDatabaseProductName());//DBMSの名称
System.out.println("db ver = " + dbmd.getDatabaseProductVersion());//DBMSのバージョン
System.out.println("table= " + table);
System.out.println("-----ResultSetMetaDataの情報-----");
rs = dbmd.getColumns(
"Sample",//カタログ名(=DB名)
null, //スキーマ名 nullの場合はすべてのスキーマが対象
table,//テーブル名 %の場合すべてのテーブルが対象
"EMAIL"//列名の条件に一致する列 %の場合すべてのカラム
);//テーブルにSelect文を投げるのと同じ属性が取れる。
while (rs.next()) {
System.out.println("TABLE_CAT="+ rs.getString("TABLE_CAT"));
System.out.println("TABLE_SCHEM="+ rs.getString("TABLE_SCHEM"));
System.out.println("TABLE_NAME="+ rs.getString("TABLE_NAME"));
System.out.println("COLUMN_NAME="+ rs.getString("COLUMN_NAME"));
System.out.println("DATA_TYPE="+ rs.getString("DATA_TYPE"));
System.out.println("TYPE_NAME="+ rs.getString("TYPE_NAME"));
System.out.println("COLUMN_SIZE="+ rs.getString("COLUMN_SIZE"));
System.out.println("BUFFER_LENGTH="+ rs.getString("BUFFER_LENGTH"));
System.out.println("DECIMAL_DIGITS="+ rs.getString("DECIMAL_DIGITS"));
System.out.println("\t" );
}
rs.close();
// データベースのクローズ
con.close();
} catch (Exception e) {
System.out.println("Exception発生");
e.printStackTrace ();
}
}
}
|
■PostgreSQLの場合
コマンド
1
2
|
javac -cp .;postgresql-42.2.5.jar MetaTest.java
java -cp .;postgresql-42.2.5.jar MetaTest
|
実行結果~PostgreSQL~
↓↓↓
■Oracleの場合
接続文字列の部分を書き換えます。
1
2
3
4
5
|
String url = "jdbc:oracle:thin:@localhost:1521/PDB2";//Oracleの接続文字列
String user = "testuser01";//DBユーザ
String password = "1234";//パスワード
String schem = "testuser01";//スキーマ
String table = "TEST0001"; //メタ情報を取得したいテーブル
|
コマンド
1
2
|
javac -cp .;ojdbc7.jar MetaTest.java
java -cp .;ojdbc7.jar MetaTest
|
実行結果~Oracle~
↓↓↓
■SQLServerの場合
接続文字列の部分を書き換えます。
1
2
3
4
5
|
String url = "jdbc:sqlserver://localhost\\SQLEXPRESS;database=test";//SQLServerの接続文字列
String user = "test01";//DBユーザ
String password = "1234";//パスワード
String schem = "sch1";//スキーマ
String table = "TEST0001"; //メタ情報を取得したいテーブル
|
コマンド
1
2
|
javac -cp .;sqljdbc42.jar MetaTest.java
java -cp .;sqljdbc42.jar MetaTest
|
実行結果~SQLServer~
↓↓↓
まとめ ~結果から気づいたこと~
- PostgreSQLのみ、getColumnsの引数ですべてのスキーマを取得条件にすると、全スキーマの情報を取得できました。
Oracle、SQLServerでは取得できた情報はユーザのデフォルトスキーマの情報のみでした。
特にSQLServerでは、接続時のスキーマを「sch1」にしたにもかかわらず、取得できた情報は「dbo」スキーマの情報だった点が意外でした。 -
PostgreSQLでは、普通のSQL文「SELECT ・・・ FROM 大文字のテーブル名」のexecuteQuery実行時にはエラーになるのですが(SQL文中のテーブル、カラム名は自動的に小文字に変換されてしまうため)、DatabaseMetaDataのgetColumnsでテーブル名を大文字で指定した場合には取得できました。
-
DBMSによって、取得できる情報に思った以上に差異がありました。
今回試した3種類のDBMSでは、どれも「TABLE_CAT」(カタログ名=データベース名)は取得できませんでした。色々調べてみたところ、MySQLでは取得できるようです。
機会があればもう少しプログラムをブラッシュアップして、実用性を高めていきたいです。
今回は以上です。ありがとうございました。