Нет, это не уловка. Два утверждения:
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 = ?
для любого значения, предоставленного для переменной связывания.
НТН