ステートメントは
SELECT * FROM tableA WHERE x = ?
パラメータはJava.sql.PreparedStatement 'stmt'を介して挿入されます
stmt.setString(1, y); // y may be null
y
がnullの場合、x = null
は常にfalse(x IS NULL
である必要がある)であるため、ステートメントはどの場合でも行を返しません。 1つの解決策は
SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL)
しかし、同じパラメーターを2回設定する必要があります。より良い解決策はありますか?
ありがとう!
私はいつもあなたがあなたの質問に示す方法でそれをしました。同じパラメーターを2回設定することはそれほど大きな困難ではありませんか?
SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL);
まったく知られていないANSI-SQL演算子がありますIS DISTINCT FROM
はNULL値を処理します。それはそのように使用できます:
SELECT * FROM tableA WHERE x NOT IS DISTINCT FROM ?
したがって、設定する必要があるパラメーターは1つだけです。残念ながら、これはMS SQL Server(2008)ではサポートされていません。
別の解決策は、使用されている値と使用されない値( 'XXX')がある場合です。
SELECT * FROM tableA WHERE COALESCE(x, 'XXX') = COALESCE(?, 'XXX')
2つの異なるステートメントを使用するだけです。
ステートメント1:
SELECT * FROM tableA WHERE x is NULL
ステートメント2:
SELECT * FROM tableA WHERE x = ?
変数をチェックして、条件に応じて適切なステートメントを作成できます。これにより、コードがより明確で理解しやすくなると思います。
[〜#〜] edit [〜#〜]ところで、ストアドプロシージャを使用してみませんか?その後、SPでこのすべてのNULLロジックを処理でき、フロントエンドの呼び出しを簡略化できます。
たとえばmysqlを使用する場合、おそらく次のようなことを行うことができます。
select * from mytable where ifnull(mycolumn,'') = ?;
次に、あなたはそうすることができます:
stmt.setString(1, foo == null ? "" : foo);
説明計画をチェックして、パフォーマンスが向上するかどうかを確認する必要があります。ただし、空の文字列はnullに等しいため、ニーズに合うとは限りません。
Oracle 11gでは、x = null
は技術的にUNKNOWN
と評価されます:
WHERE (x IS NULL AND ? IS NULL)
OR NOT LNNVL(x = ?)
OR
の前の式はNULLとNULLの同等化を処理し、その後の式は他のすべての可能性を処理します。 LNNVL
UNKNOWN
をTRUE
、TRUE
からFALSE
およびFALSE
をTRUE
に変更します。私たちが望むものの正反対なので、NOT
です。
Oracleで受け入れられたソリューションは、NOT
を含むより大きな式の一部である場合、Oracleでは機能しませんでした。