java.sql.ParameterMetaDataの続き
ParameterMetaDataが取れると、何がうれしいのかというと、与えられたSQL文(?パラメータ付き)に適切なデフォルトパラメータを与えることができ、これによって、ひとまずSQLを投げてみることができます。そうすると、そこからあらゆるメタデータが取得できるわけで、その手のツールを作っている人にはうれしかったりするのです。まあ、今のところこれが出来るのはDB2だけなのですが。
ところで、ParameterMetaDataが取れないのであれば、想像で適当な値を入れてしまえと、少し乱暴なことを思いつきました。今のところ経験則では、"0"が一番エラーを起こす確率が低いようです。以下実験結果。
- MSAccess2000 with JDBC-ODBCブリッジ
- 全て"0"でok
- hsqldb1.7.3@WindowsXP
- "0"でokなところと、そうでないところあり、ただし、setString時点でエラーが発生するため、例外をキャッチした後、setIntやsetTimestampを行うことで回避できる
- DB2 UDB v8@WindowsXP
- "0"でokなところと、そうでないところあり。executeQuery時点でエラーが発生するため、救える余地なし。素直にParameterMetaDataを使った方が良さそう。
- MSDE with SQL Server 2000 Driver for JDBC (MSDE with JDBC-ODBCブリッジ)@WindowsXP
- "0"でokなところと、そうでないところあり。executeQuery時点でエラーが発生するため、救える余地なし。
- Oracle10g@AIX
- char, varchar, number, dateは"0"でいける。あとは試してない。多分、Oracle9iと一緒。
- Oracle9i@WindowsXP
- long, clob, nclob, blob, bfile以外は"0"でいける。executeQuery時点でエラーが発生するため、救える余地なし。まあ、あんまり使わない型だからいいか。。
- Mysql3.23.53@WindowsXP with MySQL Connector/J 2.0.14 (サイトが混みあっていたようで、最新落とせなかったので、ちょい古いですが。。。)
- 全ての型が"0"でいける。型変換がかしこい!
tinyint/smallint/mediumint/integer/bigint/float/double/decimal/numeric/date/datetime/timestamp/timeyear/char/bit/bool/tinyblob/tinytext/blob/text/mediumblob/mediumtext/longblob/longtext
- Postgresql
- 未実験
まあ、そんなに型を暗黙で変換してはくれないということですね。
MSDEでのテストコード
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class Test { private static final String[] types = { "bigint", "int", "smallint", "tinyint", "bit", "decimal", "numeric", // "money", // "smallmoney", "float", "real", // "datetime", // "smalldatetime", "char", "varchar", // "text", "nchar", "nvarchar", // "ntext", "binary", "varbinary", // "image", "sql_variant", // "timestamp", // "uniqueidentifier" }; public static void main(String[] args) throws Exception { Connection con = null; PreparedStatement stmt = null; ResultSet rs = null; try { Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); con = DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;SelectMethod=cursor", "sa", "sa123"); //Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //con = DriverManager.getConnection("jdbc:odbc:sqlsvr1", "sa", "sa123"); // 全ての型について、=条件文を設定する String sqlBase = "select * from test where 1=1"; for(int i=0; i<types.length; i++) { sqlBase += " AND " + types[i] + "1 = ? "; } // 全ての条件に対し、String"0"を設定する stmt = con.prepareStatement(sqlBase); for(int i=0; i<types.length; i++) { stmt.setString((i+1), "0"); } rs = stmt.executeQuery(); } catch(SQLException e) { e.printStackTrace(); throw e; } finally { if(rs != null) { rs.close(); } if(stmt != null) { stmt.close(); } if(rs != null) { rs.close(); } } } }