2017-07-02 6 views
3

にないバインドすることはできませんコードは次のとおりです。PDO SQLiteはここで表現

<?php 
$dbh = new \PDO('sqlite:'); 
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

$goodSql = 'SELECT number FROM (SELECT 1 number UNION SELECT 2) numbers WHERE number not in (2)'; 
echo json_encode($dbh->query($goodSql)->fetchAll(PDO::FETCH_NUM)); 

$badSql = 'SELECT number FROM (SELECT 1 number UNION SELECT 2) numbers WHERE number not in (?)'; 
$binds = ['2']; 
$statement = $dbh->prepare($badSql); 
$statement->execute($binds); 
echo json_encode($statement->fetchAll(PDO::FETCH_NUM)); 
?> 

最初のステートメントが成功した結果から2を除外します。除外は、インラインSQL条件NOT IN (2)によって指定されます。

2番目のステートメントは、2を結果から除外できません。除外は、パラメータ2のPDOバインドによって条件NOT IN (?)に指定されます。

PDO/MySQLでは、2つのステートメントで同じ結果が得られます。

何が起こっていますか?これはバグですか、この結果は文書化されていますか?

P.S.私はこれをすべてのPHPバージョンでhttps://3v4l.org/otfDjを使ってテストし、5.6.0 - 5.6.30,7.0.0 - 7.2.0alpha2と同じ結果を得ました。

答えて

3

executeは、渡されたパラメータを文字列として処理するためです。

だから、あなたのクエリが "2" に等しい一切の結果は、間違いなく

$badSql = 'SELECT number FROM (SELECT 1 number UNION SELECT 2) numbers WHERE number not in ("2")'; 

そこになりません。

$badSql = 'SELECT number FROM (SELECT 1 number UNION SELECT 2) numbers WHERE number not in (?)'; 
$binds = ['2']; 
$statement = $dbh->prepare($badSql); 
$statement->bindValue(1, '2', PDO::PARAM_INT); // this is it 
$statement->execute(); 
echo json_encode($statement->fetchAll(PDO::FETCH_NUM)); 
+0

比較は、他のすべての例では、引数は浮動小数点(実)numbers.'として比較されます 'に陥ると同じではないでしょう:

ソリューションは、intようにparams expliciltyをバインドすることです? (...またはこれはsqllite固有のもので、mysqlのもの、https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html) – chris85

+0

これは内部的にどのように動作するのかわかりません。 'IN'節を評価するための規則が適用されます。しかし、両方の引数が浮動小数点数に変換されても、おそらくは同じではありません。 –

関連する問題