2017-07-02 61 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的PDO綁定在條件NOT IN (?)中指定。

在PDO/MySQL中,這兩個語句產生相同的結果。

發生了什麼事?這是一個錯誤還是記錄了這個結果?

P.S.我已使用https://3v4l.org/otfDj對所有PHP版本進行了測試,結果與5.6.0-5.6.30,7.0.0-7.2.0alpha2相同。

回答

3

這是因爲execute將傳遞參數視爲字符串。

所以,你的查詢變得

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

當然,有沒有結果,等於 「2」。

解決方法是結合PARAMS explicilty像int

$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.'是相同? (...或者這可能是特定於sqllite,那是從MySQL,https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html) – chris85

+0

不知道這是如何工作的內部,這可以規則適用於評估「IN」條款。但即使這兩個參數都轉換爲浮點數,那麼它們可能也不會相同。 –