3 回答

TA貢獻1874條經驗 獲得超12個贊
MySQL客戶端協議不允許進行多個查詢。也就是說,您已經執行了查詢,并且已經獲取了一些結果,但不是全部—然后嘗試執行第二個查詢。如果第一個查詢仍有要返回的行,則第二個查詢將收到錯誤。
客戶端庫通過在首次獲取時隱式獲取第一個查詢的所有行來解決此問題,然后后續獲取僅對內部緩存的結果進行迭代。這給他們提供了關閉游標的機會(就MySQL服務器而言)。這就是“緩沖查詢”。這與使用fetchAll()相同,這兩種情況都必須在PHP客戶端中分配足夠的內存以容納完整的結果集。
不同之處在于,緩沖的查詢將結果保存在MySQL客戶端庫中,因此,只有在依次提?。╢etch())每行之后,PHP才能訪問這些行。而fetchAll()立即為所有結果填充一個PHP數組,從而允許您訪問任何隨機行。
不使用fetchAll()的主要原因是結果可能太大而無法容納在您的PHP memory_limit中。但是看來您的查詢結果仍然只有一行,所以這應該不是問題。
您可以先關閉closeCursor()以“放棄”結果,然后再獲取最后一行。MySQL服務器收到通知,可以在服務器端放棄該結果,然后可以執行另一個查詢。在完成獲取給定結果集之前,您不應該關閉closeCursor()。
另外:我注意到您在循環內一遍又一遍地執行$ stmt2,但是每次都會返回相同的結果。根據將循環不變代碼移出循環的原理,您應該在開始循環之前執行一次,并將結果保存在PHP變量中。因此,無論使用緩沖查詢還是fetchAll(),都無需嵌套查詢。
因此,我建議您以這種方式編寫代碼:
$sql ='SELECT temp_id FROM temp1';
$stmt2 = db::db()->prepare($sql);
$stmt2->execute();
$rs2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
$stmt2->closeCursor();
$sql='SELECT COUNT(*) AS valid FROM cities_has_zipcodes
WHERE cities_id=:cities_id AND zipcodes_id=:zipcodes_id';
$stmt1 = db::db()->prepare($sql);
foreach($data AS $row)
{
try
{
$stmt1->execute($row);
$rs1 = $stmt1->fetchAll(PDO::FETCH_ASSOC);
$stmt1->closeCursor();
syslog(LOG_INFO,'$rs1: '.print_r($rs1[0],1).' '.rand());
syslog(LOG_INFO,'$rs2: '.print_r($rs2[0],1).' '.rand());
}
catch(PDOException $e){echo(sql_error($e));}
}
注意我還使用了命名參數而不是位置參數,這使得將$ row作為參數值數組進行傳遞更加簡單。如果數組的鍵與參數名稱匹配,則只需傳遞數組即可。在舊版本的PHP中,您必須:在數組鍵中包含前綴,但是您不再需要該前綴。
無論如何,您應該使用mysqlnd。它具有更多功能,具有更高的內存效率,并且其許可證與PHP兼容。

TA貢獻2041條經驗 獲得超4個贊
我希望有一個比以下更好的答案。盡管其中一些解決方案可以“解決”問題,但它們并未回答有關導致此錯誤的原因的原始問題。
設置
PDO::ATTR_EMULATE_PREPARES=>true
(我不希望這樣做)設置
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
(對我不起作用)使用
PDOStatement::fetchAll()
(并非總是可取的)$stmt->closeCursor()
每次使用之后$stmt->fetch()
(大多數情況下可以使用,但是我仍然有幾種情況沒有使用)將PHP MySQL庫從php-mysql更改為php-mysqlnd(如果沒有更好的答案,我可能會怎么做)

TA貢獻1966條經驗 獲得超4個贊
我幾乎有同樣的問題。連接到數據庫后,我的第一個查詢返回空結果并刪除此錯誤。啟用緩沖區沒有幫助。
我的連接代碼是:
try {
$DBH = new PDO("mysql:host=$hostname;dbname=$db_name", $username, $password,
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET utf8; SET NAMES utf8",
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_NUM));
}
catch(PDOException $e) { echo $e->getMessage(); }
我的解決方案是刪除初始命令:
PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET utf8; SET NAMES utf8"
這是正確的代碼:
try {
$DBH = new PDO("mysql:host=$hostname;dbname=$db_name", $username, $password,
array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_NUM));
}
catch(PDOException $e) { echo $e->getMessage(); }
并且MYSQL_ATTR_USE_BUFFERED_QUERY不是強制為true。設置為默認值。
添加回答
舉報