MySQL存储过程 - 无法重新打开表(不是临时表)

时间:2012-08-31 10:17:47

标签: mysql stored-procedures

我正在将存储过程从MS-SQL转换为MySQL。它基于有向无环图。

原始MS-SQL脚本位于以下页面的清单2中:http://www.codeproject.com/Articles/22824/A-Model-to-Represent-Directed-Acyclic-Graphs-DAG-o

存储过程保存正常,但不会从数据库中删除任何行。 我已经尝试运行Debugger for MySQL,它将第一次通过,似乎更新我用于临时数据的表,但不更新“边缘”表。它也不会在最后丢弃表格。

第二次运行,如果我手动删除purgelist表,它将运行到REPEAT语句,然后我得到错误代码:1137 SQLState:HY000,消息:无法重新打开表:'purgelist'。 本来我想使用一个临时表,但我知道我不能像我的SELECT那样多次引用临时表,但是,我很惊讶这个错误发生在非临时表上。此外,我认识到在多会话环境中我需要动态命名purgelist。

这是MySQL代码:

DELIMITER //
CREATE PROCEDURE RemoveEdge(
IN iId int(11)
)

MAIN_BLOCK: BEGIN

DECLARE counter int default 0;
DECLARE rcount int default 0;
SET counter = ( SELECT id FROM edges WHERE id = iId AND hops = 0 );
IF counter = 0 THEN
   BEGIN
      LEAVE MAIN_BLOCK;
   END;
END IF;

CREATE TABLE purgeList (id int);

-- step 1: rows that were originally inserted with the first
-- AddEdge call for this direct edge
INSERT INTO purgeList
    SELECT id
      FROM edges
      WHERE directEdgeId = iId;

-- step 2: scan and find all dependent rows that are inserted afterwards
REPEAT
    INSERT INTO purgeList
        SELECT id    
            FROM edges
            WHERE hops > 0
                AND ( entryEdgeId IN ( SELECT id FROM purgeList ) 
                    OR exitEdgeId IN ( SELECT id FROM purgeList ) )
            AND id NOT IN (SELECT id FROM purgeList );
    SET rcount = ROW_COUNT();
UNTIL rcount = 0
END REPEAT;

DELETE FROM edges
   WHERE id IN ( SELECT id FROM purgeList);
DROP TABLE purgeList;
END //
DELIMITER ;

我已经仔细检查了我的语法,但我认为那里有一个错误。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

可能有一个更干净的方法,但我认为你需要在重复中创建一个临时表,其中填充了

SELECT id FROM purgeList

然后引用临时表而不是purgeList,如下所示:

REPEAT

    CREATE TABLE innerPurgeList (id int);

    INSERT INTO innerPurgeList
       SELECT id
            FROM purgeList;

    INSERT INTO purgeList
       SELECT id    
            FROM edges
            WHERE hops > 0
                AND ( entryEdgeId IN ( innerPurgeList ) 
                    OR exitEdgeId IN ( innerPurgeList ) )
            AND id NOT IN ( innerPurgeList );
    SET rcount = ROW_COUNT();

    DROP TABLE innerPurgeList;

UNTIL rcount = 0
END REPEAT;