ГДЕ x IN (5) против ГДЕ x = 5 ... зачем использовать IN? - PullRequest
6 голосов
/ 15 мая 2009

В последнее время я заметил, что люди используют 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, верно? Но, конечно же, это сценарий only , где вы должны использовать IN?

В любом случае, спасибо за ваше время - с нетерпением жду ваших ответов!

Ответы [ 9 ]

9 голосов
/ 15 мая 2009

Может быть, неизвестно, относится ли $ visibility к одному или нескольким значениям? Не совсем подходит для вашего примера, но я видел такое использование в других местах.

8 голосов
/ 15 мая 2009

Тогда WHERE x IN (1,2,3) - лучшая альтернатива WHERE x = 1 OR x = 2 OR x = 3, верно? Но, конечно, это единственный сценарий, где вы должны использовать IN?

Нет, вы также можете использовать IN с подзапросом.

... где поле в (выбрать поле из другой_таблицы)

5 голосов
/ 15 мая 2009

Может быть, $ visibility генерируется динамически, например:

$visibility = implode(', ', array_map('intval', array(1, 2, 3)));

Где массив (1, 2, 3) может быть из ненадежных источников.

3 голосов
/ 15 мая 2009

Я думаю, что ближе к пониманию того, что делает IN.

Если вы делаете

SELECT * FROM pages WHERE is_visible = $visibility

В приведенном выше $ видимости должен быть var

Где

SELECT * FROM pages WHERE is_visible IN ($visibility)

$ visibility будет массивом данных, как @Ionut G. Stan проиллюстрировал.

Таким образом, ваш вызов будет выглядеть как is_visible IN ('1', '2', '3')

Так что теперь ваш SQL будет собирать все 1,2 и 3 строки.

Надеюсь, это имеет смысл. Это большая разница.

2 голосов
/ 15 мая 2009

Здесь нет хитрости для повышения производительности, но я не думаю, что производительность тоже пострадает. Так что оба пути в порядке. Я согласен с вами, что использование предложения IN только с одним параметром выглядит забавно, но все равно достаточно просто следовать.

Я думаю, что это, вероятно, происходит, потому что разработчик думает, что в будущем допустимо несколько значений (таким образом, запрос не будет изменен). Или, возможно, разработчик привык к сценариям, где возможны несколько значений, и они просто написали это по привычке.

2 голосов
/ 15 мая 2009

In действует для любого типа операции набора, тогда как = для одного значения. Таким образом, вы можете использовать для нескольких записей в другой таблице или любого другого типа структуры данных, которая представляет несколько значений.

1 голос
/ 15 мая 2009

Нет, это не уловка. Два утверждения:

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

почти эквивалентны. Мы видим, что эти два утверждения эквивалентны в тривиальном случае, например, когда $visibility является скаляром со значением 1.

Но утверждения не эквивалентны в нетривиальных случаях, когда $visibility содержит что-то еще. Мы можем наблюдать значительную разницу в поведении двух форм. Рассмотрим, что происходит с каждой формой, когда $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 предназначено для скалярного значения, то использование переменной bind в операторе является более безопасным подходом, поскольку он не позволяет никому вставлять «дополнительный» синтаксис SQL в оператор. (Конечно, использование переменных связывания не предотвращает все внедрения SQL, но это подходящий подход для закрытия одной дыры. Использование переменной связывания также улучшит масштабируемость, по крайней мере на некоторых платформах СУБД, таких как Oracle.)

Рассмотрим, что происходит, когда мы используем переменную связывания (заполнитель), которая, как мы знаем, НЕ будет интерпретироваться как синтаксис SQL. Мы видим, что два утверждения ARE действительно эквивалентны:

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

для любого значения, предоставленного для переменной связывания.

НТН

0 голосов
/ 16 мая 2009

Тогда ГДЕ x IN (1,2,3) лучше альтернатива ГДЕ x = 1 ИЛИ x = 2 ИЛИ х = 3, верно? Но, конечно же, это Единственный сценарий, где вы должны использовать IN?

IN () и OR синтаксически эквивалентны. Изучение плана выполнения ваших двух предложений покажет это. IN () просто является более эффективной и простой для понимания нотацией.

0 голосов
/ 15 мая 2009

«WHERE x IN (1,2,3)» в любом случае совпадает с «WHERE x = 1 ИЛИ x = 2 ИЛИ x = 3».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...