Você está certo de que o primeiro caso é inseguro. É importante entender, porém, que preparar uma instrução só tem valor se você estiver usando dados variáveis e/ou executando a mesma consulta repetidamente. Se você estiver executando instruções simples sem variáveis , você poderia simplesmente fazer isso:
$sql = "SELECT * from myTable WHERE this_column IS NOT NULL";
$result = $conn->query($sql);
E termine com um
PDOStatement
objeto para trabalhar, assim como quando você usa PDO::exec()
. Para o seu segundo caso, novamente, você está amplamente correto. O que está acontecendo é que a variável passada para o banco de dados é escapada e citada (a menos que você especifique o contrário com o terceiro argumento para
PDOStatement::bindParam()
, ele é enviado como uma string, o que é bom para a maioria dos casos.) Portanto, a consulta não "falhará" se dados incorretos forem enviados. Ele se comporta exatamente como se você tivesse passado um número válido que não existia como ID no banco de dados. Existem, é claro, algumas casos extremos
onde você ainda está vulnerável mesmo com uma declaração preparada corretamente. Além disso, para facilitar a vida, você pode usar instruções preparadas como esta, para fazer a ligação implícita:
$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->execute([":id"=>$id]);
Ou mesmo assim, com parâmetros sem nome:
$sql = "SELECT * FROM myTable WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->execute([$id]);
Naturalmente, a maior parte disso foi explicada nos comentários enquanto eu digitava a resposta!