hhelibexさんのblogエントリより:
- パラメータマーカーに指定する文字列が長すぎるとSQLエラー - 気まぐれ日記
上記はhhelibexさんがDB2のPREPAREの動きで疑問を感じているという内容です。詳しくは上のエントリを読んでいただくとして疑問を簡単に説明すると、"CREATE TABLE HOGE(ID SMALLINT, NAME VARCHAR(10))"と定義したNAME列に対して
> SELECT ID, NAME FROM HOGE WHERE NAME = '0123456789a' (※リテラル文字列が11バイトある)
だとエラーなく動くのに、
> SELECT ID, NAME FROM HOGE WHERE NAME = ?
としておいて、PREPAREでパラメーターマーカー(?のところ)に11バイト以上の長さの文字列を当てはめようとするとSQL-302エラーが返ってくるというわけです。(DB2以外のRDBMSだとエラー無く動く場合が多いようです)
これはDB2の仕様通りの動きです。エラー(SQL-302)の意味は
> SQL0302N EXECUTE または OPEN ステートメント内のホスト変数の値が大きすぎます。
である事から分かるようにパラメーターマーカー(ここではホスト変数と書かれていますが)のサイズ(型)をチェックしている事からくるエラーなのです。つまりDB2はPREPAREでパラメーターマーカーに値を入れる際にパラメーターマーカーの型と、値(リテラル)に互換性があるかをチェックしています。
パラメーターマーカーに型があるのかと思われるかもしれませんが、DB2はNULLであれパラメーターマーカーであれ、型が存在します(型を評価しようとします)。この場合は"WHERE NAME = ?"ですからNAME型のVARCHAR(10)が?の型と類推されます。?がVARCHAR(10)なのにPREPAREで11バイトの文字列を当てはめようとするので、そこでエラーが出ているわけです。
これをエラー無く動作させたい場合は?に11バイト以上入る型を与えれば良いわけです。SQLで型を指定するにはCASTを使用します。つまりPREPAREの時点で
> SELECT ID, NAME FROM HOGE WHERE NAME = CAST(? AS VARCHAR(100))
等とするとエラー無く動作します。お試しあれ。(一応手元の環境でで小さいプログラムを組んで試しましたので、大丈夫だと思います。)
このように、DB2の型に関する厳密さは他のRDBMSとDB2とで共通コードを書こうとした時に、注意しなくてはいけない点の一つです。NULLの扱いに関しては以下に書いています。
- DB2小ネタ - DB2ではNULLをSELECTに単純には置けない
こういった型への厳密さは他RDBMSからの移植の妨げになり得たのですが、DB2 9.7では"緩い型付け"モードが追加されて上記のような他RDBMSとの非互換が起こりにくくなっています。(DB2 9.7で上記がCAST無しで通るのかは確認できていないです)
タイムリーなことに日付が変わって19日になりました:) 今日がDB2 9.7の出荷開始日です!
- パラメータマーカーに指定する文字列が長すぎるとSQLエラー - 気まぐれ日記
Oracle、PostgreSQL、MySQLではSELECTとDELETEは正常終了するのに、DB2は、SELECTとDELETEでもエラーになる。
上記はhhelibexさんがDB2のPREPAREの動きで疑問を感じているという内容です。詳しくは上のエントリを読んでいただくとして疑問を簡単に説明すると、"CREATE TABLE HOGE(ID SMALLINT, NAME VARCHAR(10))"と定義したNAME列に対して
> SELECT ID, NAME FROM HOGE WHERE NAME = '0123456789a' (※リテラル文字列が11バイトある)
だとエラーなく動くのに、
> SELECT ID, NAME FROM HOGE WHERE NAME = ?
としておいて、PREPAREでパラメーターマーカー(?のところ)に11バイト以上の長さの文字列を当てはめようとするとSQL-302エラーが返ってくるというわけです。(DB2以外のRDBMSだとエラー無く動く場合が多いようです)
これはDB2の仕様通りの動きです。エラー(SQL-302)の意味は
> SQL0302N EXECUTE または OPEN ステートメント内のホスト変数の値が大きすぎます。
である事から分かるようにパラメーターマーカー(ここではホスト変数と書かれていますが)のサイズ(型)をチェックしている事からくるエラーなのです。つまりDB2はPREPAREでパラメーターマーカーに値を入れる際にパラメーターマーカーの型と、値(リテラル)に互換性があるかをチェックしています。
パラメーターマーカーに型があるのかと思われるかもしれませんが、DB2はNULLであれパラメーターマーカーであれ、型が存在します(型を評価しようとします)。この場合は"WHERE NAME = ?"ですからNAME型のVARCHAR(10)が?の型と類推されます。?がVARCHAR(10)なのにPREPAREで11バイトの文字列を当てはめようとするので、そこでエラーが出ているわけです。
これをエラー無く動作させたい場合は?に11バイト以上入る型を与えれば良いわけです。SQLで型を指定するにはCASTを使用します。つまりPREPAREの時点で
> SELECT ID, NAME FROM HOGE WHERE NAME = CAST(? AS VARCHAR(100))
等とするとエラー無く動作します。お試しあれ。(一応手元の環境でで小さいプログラムを組んで試しましたので、大丈夫だと思います。)
このように、DB2の型に関する厳密さは他のRDBMSとDB2とで共通コードを書こうとした時に、注意しなくてはいけない点の一つです。NULLの扱いに関しては以下に書いています。
- DB2小ネタ - DB2ではNULLをSELECTに単純には置けない
こういった型への厳密さは他RDBMSからの移植の妨げになり得たのですが、DB2 9.7では"緩い型付け"モードが追加されて上記のような他RDBMSとの非互換が起こりにくくなっています。(DB2 9.7で上記がCAST無しで通るのかは確認できていないです)
タイムリーなことに日付が変わって19日になりました:) 今日がDB2 9.7の出荷開始日です!










