2009-05-15 17 views
6

私が最近気付いたのは、INを使用している人が不適切であると思われる人です。私はトリックを見逃しているように感じています - おそらく速度の向上や何かがありますか?x IN(5)とWHERE x = 5 ...なぜINを使用するのですか?

このクエリ:

SELECT * FROM pages WHERE is_visible IN ($visibility) 

なぜそれを使うのか?なぜ:

SELECT * FROM pages WHERE is_visible = $visibility 

確かに、それはこのだったら:

SELECT * FROM pages WHERE is_visible 
IN ($visibility,$invisibility,$somethingelse) 

その後WHERE x IN (1,2,3)は右、WHERE x = 1 OR x = 2 OR x = 3へのより良い代替手段ですが?しかし、確かにこれはのINだけを使うべきですか?

お時間をいただきありがとうございます - 私はあなたの返信を楽しみにしています!

+1

返信いただきありがとうございます。この場合、$ visiblityは信頼され、常に0または1です。だから、 "WHERE ... IN ..."というこの使い​​方は、結局は不要です! – ledneb

+1

今は必ずしも常に意志を意味するわけではありません。開発者は「ちょうどその時」の瞬間に備えることができます。 –

+0

YAGNI。ちょうど場合の場合は決して来ない。 –

答えて

2

あり、パフォーマンスを向上するためにここにはトリックはありませんが、私はどちらかヒット任意のパフォーマンスがあるとは思いません。だから両方の方法はOKです。 1つのパラメータでIN句を使用すると面白く見えると思いますが、それに続くのはまだ簡単です。

これはおそらく、開発者は将来的に複数の値が許可されている可能性が高いと考えていると思います(この方法ではクエリは変更されません)。あるいは、開発者は、複数の値が可能なシナリオに慣れていて、習慣からそんなことを書いただけかもしれません。

+2

キップ私はあなたが間違っていると思います。明らかに、INはINと同じではないので、INを完全に理解していません。もし彼が何を言っていたのなら "x IN(1,2,3)はどこのx = 1かx = 2かx = 3の方がいいでしょうか?" – Lee

+1

ありがとうございます。私はその質問に対するすべての答えは素晴らしいと思っていますが、あなた自身が質問に答えてくれます:) – ledneb

+0

@Lee:コメントはあなたの答えに属していますが、コメントはこの回答に関係していません。 – Kip

8

WHERE x IN (1,2,3)WHERE x = 1 OR x = 2 OR x = 3のより良い代替品ですか?しかし、確かにこれはINを使用する唯一のシナリオですか?

いいえ、INにはサブクエリも使用できます。このような(another_tableから選択フィールド)のフィールドが

+0

ありがとう、キップ。 –

+0

それは良い点です。私はINがサブクエリと共に使用できるとは考えていませんでした – ledneb

5

はたぶん$視認性が動的に生成される

...、:

$visibility = implode(', ', array_map('intval', array(1, 2, 3))); 
配列(1、2、3)信頼できないから来るかもしれない

ソース。

9

多分、$ visibilityが単一の値または複数の値を参照するのは不明ですか?あなたの例にはあまり合いませんが、私は他の場所でそのような使用を見ました。

+2

私もこのことを見ました...メモリはまだ私を悩ましています。 – rmeador

+0

Mmm良い点 - この場合でもvisiblityは常に0または1です – ledneb

+0

$ visibilityが複数の値を参照する場合、それらの値はどのようにsqlに展開されますか? $ visibility = '1,2,3'なら、これはあまり意味がありません:SELECT * FROMページWHERE is_visible IN( '1,2,3') – ErikE

0

「WHERE x IN(1,2,3)」は、「WHERE x = 1 OR x = 2 OR x = 3」と同じです。

2

Inは、どんな種類のセット操作でも動作しますが、=は単一の値になります。したがって、別のテーブルの複数のレコード、または複数の値を表す他の種類のデータ構造を使用することができます。

3

INが何をしているのかを理解するのがポイントだと思います。だからあなたのSQLは、すべての場所is_visible = 1

どこ

SELECT * FROM pages WHERE is_visible IN ($visibility) 
収集し、= 1 is_visibileよう

あなたは上記の$の可視性で

SELECT * FROM pages WHERE is_visible = $visibility 

を行う場合は、VARでなければならないであろう

$ visibilityは@Ionut Gのようなデータの配列になります。

だからあなたの呼び出しはis_visibleのようになります( '1'、 '2'、 '3')

だから今、あなたのSQLは、すべての1,2 & 3行を収集します。

希望は意味があります。その大きな違いです。

+0

これは彼の質問にどう答えているのか分かりません。彼はINが何を意味するのかよく知っているようだ。 – Kip

+0

@Lee:あなたのコメントからあなたが間違った答えをしている:>>キップあなたが間違っていると思う。明らかに、INはINと同じではないので、INを完全に理解していません。もし彼が何を言ったのか「それでx IN(1,2,3)はどこのx = 1かx = 2かx = 3の方がいいのでしょうか?」 "事実は" X IN(1 、2,3) "* IS *は" X = 1 OR X = 2 OR X = 3 "と事実上同じです。あなたがそうではないと言ったら、どのような状況で異なるクエリ結果を出すでしょうか?データベースエンジンの実装に違いがあるかもしれませんが、ブラックボックスの観点との違いはありません。 – Kip

1

いいえ、それはトリックではありません。 2つのステートメント:

SELECT * FROM pages WHERE is_visible IN ($visibility) 
SELECT * FROM pages WHERE is_visible = $visibility 

はほぼ同等です。我々は2つの文には、例えば、1

の値を持つスカラとき$visibilityで、些細な場合は同等であることを観察する。しかし$visibilityは何か他のものが含まれている場合ステートメントは、非自明な例で同等ではありません。我々は、2つの形態の行動における有意差を観察することができる。 $visibilityは、これらの例の値を含む文字列である場合に、各フォームに何が起こるかを考えてみましょう:

 
    '1,2,3' 
    '1 OR 1=1' 
    'select v.val from vals v' 

我々は二つの形式から生成された結果のSQL文で有意差を観察する:

 
    SELECT * FROM pages WHERE is_visible IN (1,2,3) 
    SELECT * FROM pages WHERE is_visible = 1,2,3 
 
    SELECT * FROM pages WHERE is_visible IN (1 OR 1=1) 
    SELECT * FROM pages WHERE is_visible = 1 OR 1=1 

ここでは、どちらの形式のステートメントでも、SQLインジェクションの可能性が大いに懸念されています。 $visibilityがスカラー値の場合、ステートメントにバインド変数を使用する方が、「余分な」SQL構文をステートメントに入れることを避けるため、より安全な方法です。 (もちろん、バインド変数を使用してもすべてのSQLインジェクションが阻止されるわけではありませんが、バインド変数を使用すると、少なくともOracleなどの一部のDBMSプラットフォームではスケーラビリティが向上します)。

バインド変数(プレースホルダ)を使用するとどうなりますか?わかっているのは、ではなくをSQL構文として解釈することです。我々は2つの文が実際に同等をしていることを守ってください。

 
    SELECT * FROM pages WHERE is_visible IN (?) 
    SELECT * FROM pages WHERE is_visible = ? 

バインド変数のために供給任意の値のために。

HTH

+0

あなたはまだINまたは同等のSQLインジェクションの可能性がありますが、この答えは質問には関係ありません。 – Kip

+0

キップ、あなたは正しいです。それが私が指摘しようとしていたものです。元の質問は、彼らが「何かを見逃している」かどうかを尋ねた。あなたもそれを逃したようです。いずれの変種もSQLインジェクションを防ぎません。これは、バインド変数を使用して最も簡単に解決されます。その場合、NULL値が指定されていても、文は同じでなければなりません。バインド変数を使用しない場合、ステートメントは異なる方法で脆弱である点で異なる_SIGNIFICANTLY_であり、$ visibilityに何が含まれているかに関する情報は提供されません。私の答えは関連しています。 – spencer7593

0

その後にここでX IN(1,2,3)であり、良好 代替ここで、x = 1またはX = 2 OR X = 3、右?しかし、確かにこれは のINシナリオだけですか?

IN()とORは構文的に同等です。 2つの提案の実行計画を調べると、これが表示されます。 IN()は、単により効率的で分かりやすい表記法です。

関連する問題