1

ストアド プロシージャを MS-SQL から MySQL に変換しています。有向非巡回グラフに基づいています。

オリジナルの MS-SQL スクリプトは、次のページのリスト 2 にあります

ストアド プロシージャは正常に保存されますが、データベースから行を削除していません。Debugger for MySQL を実行してみましたが、初回は成功し、一時データに使用しているテーブルを更新しているように見えますが、「エッジ」テーブルは更新されません。また、最後にテーブルをドロップしません。

2 回目の実行では、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 に答える