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

IN句

UPDATE ACCOUNT SET DELFLAG = TRUE WHERE ID IN (7,8,10);

このようにまとめて削除フラグ(DELFLAG)を更新する場合に、INを使うと思います。
ここでIDの型はINTEGERです。
もちろん、実行結果は3レコードが更新されます。


次にこのように書いてみます。

UPDATE ACCOUNT SET DELFLAG = TRUE WHERE ID IN ('7','8','10');

これの実行結果は1レコードとなりました。

まとめると、
IN句に指定するカラムの型がINTEGERにも関わらず、文字列として指定した場合、
最適化で更新対象行の絞込みがおかしくなるようです。

まぁそもそも、INTEGERの型のところを文字列型で指定してるのがというツッコミは無しで。


追記
H2のオプションで

h2.optimizeIn

というのがあり、これがデフォルトでtrueになってます。
これを

-Dh2.optimizeIn=false

のように、Tomcatの起動パラメータに付加すると期待通りの動作をしました。
org.h2.expression.ConditionIn#optimizeで何かやってるっぽいです。


さらに追記
それぞれで、EXPLAINを実行してみました。

EXPLAIN UPDATE ACCOUNT SET DELFLAG = TRUE WHERE ID IN (7,8,10);
結果
UPDATE PUBLIC.ACCOUNT /* PUBLIC.PRIMARY_KEY_17: ID >= 7 AND ID <= 10 */
SET DELFLAG = TRUE
WHERE ID IN(7, 8, 10)
EXPLAIN UPDATE ACCOUNT SET DELFLAG = TRUE WHERE ID IN ('7','8','10');
結果
UPDATE PUBLIC.ACCOUNT /* PUBLIC.PRIMARY_KEY_17: ID >= '10' AND ID <= '8' */
SET DELFLAG = TRUE
WHERE ID IN('7', '8', '10')

はい、後者の方はみごとに範囲指定が間違ってます。


さらにさらに追記
比較をjava.text.Collatorで行っているようで、
下記コードでテスト。

  Collator collator = Collator.getInstance();
  int result = collator.compare("10","8");
  System.out.println(result);

結果は見事に「-1」でした。