No, it's not a trick. The two statements:
SELECT * FROM pages WHERE is_visible IN ($visibility)
SELECT * FROM pages WHERE is_visible = $visibility
are nearly equivalent. We observe that the two statements are equivalent in the trivial case, for example, when $visibility
is a scalar with a value of 1.
But the statements are not equivalent in the non-trivial cases when $visibility
contains something else. We can observe a significant difference in behavior of the two forms. Consider what happens with each form when $visibility
is a string containing these example values:
'1,2,3'
'1 OR 1=1'
'select v.val from vals v'
We observe a significant difference in the resultant SQL statements generated from the two forms:
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
A large concern here, with either form of the statement, is the potential for SQL injection. If $visibility
is intended to be a scalar value, then using a bind variable in the statement is a more secure approach, since it avoids anyone from sliding 'extra' SQL syntax into the statement. (Of course, using bind variables doesn't prevent all SQL injection, but it is suitable approach to closing one hole. Using a bind variable will also improve scalability, at least on some DBMS platforms such as Oracle.)
Consider what happens when we use a bind variable (placeholder), which we know will NOT be interpreted as SQL syntax. We observe that the two statements ARE indeed equivalent:
SELECT * FROM pages WHERE is_visible IN ( ? )
SELECT * FROM pages WHERE is_visible = ?
for any value supplied for the bind variable.
HTH