読者です 読者をやめる 読者になる 読者になる

テーブルのカラムへの null 値の代入

PreparedStatement を用いて null を入れる場合、

statement.setObject(index, null)

とするのがお手軽ではありますが、SQL Server では binary, varbinary 型のカラムに setObject で null を入れられません。

そこで、仕方なく setNull を使うのですが、setNull は他の set*** 系メソッドと違い、第二引数にカラムの JDBC 型を渡す必要があり、面倒です。

PreparedStatement であれば、こいつの getParameterMetaData や getMetaData で SQL 発行前に ParameterMetaData, ResultSetMetaData を取得できるのですが、JDBC ドライバは PreparedStatement#(getParameterMetaData|getMetaData) で null を返してもよい仕様になっている(そして、大抵の JDBC ドライバがそうする)ため、これだけでは不安です。

というわけで、java.sql.Types.NULL を使いましょう。
見落とされがちな SQL タイプですが、javadoc にはきちんと「総称 SQL 値 NULL を識別します」と書かれています。

要は、SQL Server の binary, varbinary に対しては、setObject(index, null) の代わりに、setNull(index, java.sql.Types.NULL) を使いましょう、ということです。
※追記
setXxx(数値型の場合、setObject、それ以外の場合、setString 等)で null を入れると、すべてうまくいくようです。

以下、調査結果の抜粋です。

  • setObject(index, null)
    • SQL Server では、binary, varbinary 型のカラムに対してはエラー
    • 自分が試した限り、PostgreSQL8.3, Oracle11g, DB2 9.7 では問題なし
  • setNull(index, java.sql.Types.NULL)
    • SQL Server では、date, datetime2, float, text, ntext, real, time 型のカラムに対してはエラー
    • 自分が試した限り、PostgreSQL8.3, Oracle11g, DB2 9.7 では問題なし
    • setXxx
      • 数値型に対しては setObject(setInt や setDouble には null を渡せないため)、それ以外、例えば varchar や binary には setString(null), setBinary(null) とする方法
      • DB2, Oracle, PostgreSQL, SQL Server の各カラムで正常動作