1

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

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

存储过程保存得很好,但没有从数据库中删除任何行。我已经尝试通过 Debugger for MySQL 运行,它会第一次通过并且似乎更新了我用于临时数据的表,但不更新“edges”表。它也不会在最后丢弃表格。

第二次运行,如果我手动删除 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 ;

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

4

1 回答 1

2

可能有一种更简洁的方法,但我认为您需要在 Repeat 中创建一个临时表,其中填充有

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;
于 2012-08-31T10:31:01.840 回答