2010-11-18 13 views
39

文がyがnullの場合x = nullが常にあるので、文はすべての場合には行を戻さないPreparedStatementでnull値を扱う方法(多分)?

SELECT * FROM tableA WHERE x = ? 

で、パラメータがのjava.sql.PreparedStatement「のstmt」を介して挿入されている

stmt.setString(1, y); // y may be null 

false(x IS NULLである必要があります)。 1つのソリューションは

SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL) 

ですが、同じパラメータを2回設定する必要があります。より良い解決策はありますか?

ありがとうございます!

ステートメント1:

SELECT * FROM tableA WHERE x is NULL 

書2:

SELECT * FROM tableA WHERE x = ? 

あなたの変数をチェックし、状況に応じて適切なステートメントを構築することができ

+0

私は準備文を使用しません。私はSQL文字列を使用して、SQL文字列で '= NULL'を' Is Null'に置き換えます。魅力のように動作します。 –

+19

これはタイプセーフではなく、おそらく注射攻撃に対して脆弱です。 – aioobe

答えて

29

私はいつもあなたの質問にあなたの方法でそれを行ってきました。同じパラメータを2回設定することは、それほど大きな苦労ではありませんか?あなたのかどうかを確認するための計画を説明

stmt.setString(1, foo == null ? "" : foo); 

はあなたがチェックしなければならない:ヨーヨーを行うことができます次に

select * from mytable where ifnull(mycolumn,'') = ?; 

:あなたは、インスタンスのmysqlのために使用している場合

SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL); 
+0

ご連絡ありがとうございました。だからあなたは「これはベストプラクティス」に投票しますか? – Zeemee

+0

私は良い方法を見つけたことはありません。 –

+4

ただし、パフォーマンスが重要な場合は、2つの別個のSQLを使用することをお勧めします.IS NULLを使用するかどうかによってアクセス・パスが異なるためです。 – Thilo

5

はちょうど2つの異なる文を使用します。私は、これによりコードをもっとはっきりと理解しやすくなると思います。

EDIT ところで、なぜストアドプロシージャを使用しないのですか?その後、SPのこのすべてのNULLロジックを処理することができ、フロントエンドコールの作業を簡素化できます。

+0

ありがとうdcp、これはまっすぐ私に見えます。私の声明が1つのパラメータを持っていないのではないかと想像してください。しかし、私は5^2 Statements = 25が必要です! – Zeemee

+0

これは、 '' IS 'の代わりに '='と表示されるという問題を避けるでしょうか? – aioobe

+1

@dcp、あなたは答えをあるものから全く異なるものに変更したようです。どうして? –

0

あなたはおそらくのような何かを行うことができますパフォーマンスが向上します。空の文字列がnullに等しいことを意味するので、それはあなたのニーズに合うとは認められません。

+1

ありがとうございました。しかし、空の文字列が値として使用されていないことを確認できません。 – Zeemee

+0

パフォーマンスが本当に必要な場合は、テストするために決して存在しないと確信している値を選ぶことができます。これはパフォーマンスのハックなので、できればそれを避けたいと思います。 (例えば、あなたのデータには€が含まれていない可能性がありますので、 ''の代わりにそれをチェックすることができます。 – Knubo

8

NULL値を処理する全く知られていないANSI-SQL演算子IS DISTINCT FROMがあります。次のように使用できます。

SELECT * FROM tableA WHERE x NOT IS DISTINCT FROM ? 

したがって、1つのパラメータのみを設定する必要があります。残念ながら、これはMS SQL Server(2008)ではサポートされていません。x = nullは技術的にUNKNOWNに評価されるためのOracle 11gでは

SELECT * FROM tableA WHERE COALESCE(x, 'XXX') = COALESCE(?, 'XXX') 
+0

MySQL + PHP PDOで試してみてください。 – Pere

+1

[IS DISTINCT FROM](https://www.postgresql.org/docs/current/static/functions-comparison.html)はPostgreSQLでうまくいきます –

+0

古いバージョンのOracleでは、NVLを同じものに使うことができますが可能であればCOALESCEはより良いです(https://stackoverflow.com/questions/950084/oracle-differences-between-nvl-and-coalesceを参照)。 –

0

、私はそれをこのように実行します。

別の解決策があると(「XXX」)決して使用される値がある場合は、次のようになります。

WHERE (x IS NULL AND ? IS NULL) 
    OR NOT LNNVL(x = ?) 

表現ORはNULLとNULLを等しくするの世話をする前に、その式は、後に他のすべての可能性の世話をします。 LNNVLUNKNOWN私たちが何をしたいの正反対、それゆえNOTですTRUE、へTRUEFALSEへとFALSETRUEに変化します。

Oracleでは、受け入れられた解決策が、より大きな表現の一部であったときに、NOTを含む一部のケースで、私にとってうまく機能しませんでした。

関連する問題