2013-01-02 114 views
3

我正在使用PDO調用以DROP TABLE IF EXISTS開頭的存儲過程。我隨機得到PDOException'SQLSTATE [42S02]:未找到基本表或視圖:1146表'historygr.reached'不存在',甚至更煩人它會告訴我,拋出一個異常說,表已經存在,幾秒鐘之內,似乎從相同的連接。PDOException與DROP TABLE IF EXISTS

我不能自己觸發錯誤,但我得到它的錯誤通知。

下面是錯誤的起源於PHP:

$dbh = PDODB::getInstance(); 
$stmt = $dbh->query("CALL ListReached(".$this->item_id.")"); // <-- ERROR 
$items = $stmt->fetchAll(); 

而這裏的MySQL的過程定義:

DELIMITER $$ 
CREATE DEFINER=`root`@`localhost` PROCEDURE `ListReached`(IN root INT) 
BEGIN 
    DECLARE rows SMALLINT DEFAULT 0; 

    DROP TABLE IF EXISTS reached; 
    CREATE TABLE reached(
    node_id INT PRIMARY KEY 
    ) ENGINE=HEAP; 

    INSERT INTO reached VALUES (root); 
    SET rows = ROW_COUNT(); 

    WHILE rows > 0 DO 
    INSERT IGNORE INTO reached 
     SELECT DISTINCT child_id 
     FROM related_item AS r 
     INNER JOIN reached AS p ON r.parent_id = p.node_id; 
    SET rows = ROW_COUNT(); 

    INSERT IGNORE INTO reached 
     SELECT DISTINCT parent_id 
     FROM related_item AS r 
     INNER JOIN reached AS p ON r.child_id = p.node_id; 
    SET rows = rows + ROW_COUNT(); 
    END WHILE; 

    DELETE FROM reached WHERE node_id = root; 

    SELECT * FROM reached; 
    DROP TABLE reached; 

END 

回答

1

你打比賽的條件。

如果兩個連接都執行相同的腳本,它們將創建和刪除相同的表,導致衝突。

考慮使用臨時表,而不是在事務中創建和刪除實際表。

http://dev.mysql.com/doc/refman/5.1/en/create-table.html

創建表時,您可以使用TEMPORARY關鍵詞。 TEMPORARY表僅對當前連接可見,並在關閉連接時自動刪除。這意味着兩個不同的連接可以使用相同的臨時表名稱而不會相互衝突,也不會使用同名的現有非TEMPORARY表衝突。 (直到臨時表被刪除時,現有表纔會隱藏。)要創建臨時表,您必須具有CREATE TEMPORARY TABLES特權。

編輯

正如評論mentionned,查詢正在引用多個時間表。

另一種方法是使用過程中鎖:http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html#function_get-lock

+0

遺憾的是不能使用一個臨時表,因爲你不能引用他們不止一次在查詢這是何等的程序功能 –

+0

呀,你會需要創建一個臨時表的副本來多次引用它(每個引用n-1個副本),或者更改您的查詢,而不是多次引用臨時表。 –