2014-08-29 51 views
1

This question without an accepted answer在修改後的窗體中,我在MySQL版本5.6.16上遇到了MySQL的災難性問題。PDOStatement :: nextRowSet()在Windows上的MySQL 5.6.16中損壞

的問題是容易複製:包括我在這裏(從上面鏈接的問題複製,但適用於我的代碼更改):

$pdo = /* connection stuff here */ 
$sql = "call test();"; // call stored procedure - see below 
$statement = $connection->query($sql); 
do { 
    $rowset = $statement->fetchAll(PDO::FETCH_ASSOC); 
    if($rowset) { 
     // Do stuff with $rowset 
    } 
} while($statement->nextRowset()); 

這裏是存儲過程test的定義:

DELIMITER $$ 
DROP PROCEDURE IF EXISTS `test`$$ 
CREATE PROCEDURE `test`() 
BEGIN  
    SELECT 1; SELECT 2; SELECT 3; SELECT 4; 
END$$ 
DELIMITER ; 

我的代碼和上面鏈接的代碼之間的唯一區別是我將SQL查詢打包到存儲過程中。

在我的情況下,while聲明返回true四次,而不是三次(應該只是三次)。第四次後,fetchAll(...)拋出SQLSTATE[HY000]: General error錯誤。

不幸的是,這個問題是災難性的。除了使用nextRowSet()函數之外,沒有其他方式可以使用PDO迭代到以下行集。因此,爲了解決此問題,我可能會恢復到以前版本的MySQL。

我發現,似乎表明這個問題兩個環節,在這裏列出: https://bugs.php.net/bug.php?id=67130http://permalink.gmane.org/gmane.comp.php.devel/81518

我希望確認,這的確是與Windows的MySQL 5.5.16的版本中的錯誤。更多的,我會很感激一個解決方法。謝謝。

+0

['mysqli'](http://php.net/mysqli) 「罐」([我記得](http://php.net/manual/en/ mysqli.multi-query.php))在結果集之間切換,但它需要將整個應用程序移動到另一個數據庫交互層。 – BlitZ 2014-08-29 08:09:42

+1

爲什麼不能將所有這些字符串作爲4個單獨的查詢來運行? – silkfire 2014-08-29 08:17:48

+0

@silkfire我已經更新了我的問題以添加重要的細節(當我第一次發佈該問題時不這樣做)。現在,代碼與我所運行的代碼完全相同。實際上,SQL嵌入在存儲過程中。對於我的實際應用程序,查詢要複雜得多,不容易重構。 – 2014-08-29 08:27:30

回答

-1

如果問題是由多個結果集引起的,那麼最好的解決方法是找到避免單個查詢中多個結果集的方法。例如,如果預期的結果格式相同(我預計它們可能是因爲您打算使用相同的代碼來處理它們),那麼您可以使用UNION將這四個查詢合併到一起。

SELECT 1 
UNION ALL 
SELECT 2 
UNION ALL 
SELECT 3 
UNION ALL 
SELECT 4; 

如果失敗,您可以對每個SELECT執行一個單獨的查詢,並將結果交給一個函數來處理。

2

我和PDO :: nextRowset()有同樣的問題,因爲即使沒有更多的行集可用,它也會返回true,因此當調用fetchAll()時,會引發異常HY000。 (在PHP 5.5.12 windows,Mysql 5.5.17 linux上測試)

這個問題的解決方法是在獲取行集之前用方法PDO :: columnCount()檢查列的數量。如果它不是零,那麼你有一個有效的行集,因此你可以調用PDO :: fetchAll()。

即使PDO :: nextRowset()報告爲true,columnCount()也會在移動到下一個行集之前報告列數。

實施例:

while ($objQuery->columnCount()) { 
    $tab[] = $objQuery->fetchAll(\PDO::FETCH_ASSOC); 
    $objQuery->nextRowset(); 
}