JDBC の制限を回避するためのパターンを実装しています。プリペアド ステートメントの場合、JDBC はプレースホルダーの数を 2100 に制限しています。これを回避するために、2100 以上の値を含む xml 文字列を使用し、関数 tf_splitxml を使用して SQL Server 側で解析しています。準備済みステートメントを使用する〜4 Javaメソッドに対してこれを行っています。
この tf_splitxml は、すべての値を含む単一の列「トークン」を構築するだけです。したがって、次のxml文字列:
'<node><value>1</value><value>2</value></node>'
値が 1 と 2 の 2 つの行を含む列に変換されます。
このパターンは、select ステートメントではうまく機能しているように見えますが、update ステートメントでは失敗しています。一般的なパターンは次のとおりです。
declare @xml xml; set @xml = ?; --Replaced with xml string in PreparedStatement
update tableX
...
where ids in (select token from tf_splitxml(@xml));
nvarchar 値をデータ型 int に変換するときに変換に失敗したことがわかります。[上記の xml 文字列の場合]。奇妙なことに、準備されたステートメントによって設定されたクエリを抽出すると、SQL Server で完全に実行できます。
私の考え:
- 4 つの方法のうち、3 つはこの xml パターンを使用して機能します。これら 3 つはすべて select ステートメントであり、executeQuery() を使用します。失敗した 4 番目のメソッドは update ステートメントで、executeUpdate() を使用します。おそらく問題は、準備されたステートメントがSQLをプリコンパイルする方法に関係していますか?
私が試したこと:
tf_splitxml から生成されたトークンを保持できるテーブルを作成しました。失敗したメソッドの場合、JDBC がエラーをスローする前に tf_splitxml が呼び出されることはありません。
Java 側では、ps.setString(index, convertToXML(idsArray)) を使用しています。@xml が文字列ではない (xml 変数として宣言されている) 場合でも、これは最初の 3 つのメソッドで機能します。これを SQLXML オブジェクトに切り替えてみましたが、役に立ちませんでした。私はまだ同じ 3/4 メソッドを適切に動作させています。
準備したすべてのクエリを SQL Server エディター内で直接実行できます。
よろしくお願いします!:)