SQL游标消除

时间:2014-12-22 09:38:01

标签: sql sql-server tsql cursor

我需要在将新表引入db之后在我的应用程序中迁移数据。我为此准备了SQL脚本,但是它使用了游标,由于性能问题我想要消除它(配置表中最多2m的记录)。

我到底需要做的是:

配置中的foreach配置,其中 related_id 不为空我需要将id = related_id TypeA 实体迁移到 TypeB ; 将 ElementA 类型的所有实体(在 TypeA_id 列中引用 TypeA )迁移到 ElementB ;我还需要将配置上的 related_id 更新为新创建的 TypeB ,并删除已迁移的 ElementA TypeA < / strong>实体。

DECLARE @RELATED INT,
    @CURRENT_CONFIG INT,
    @CREATED INT

DECLARE Crs SCROLL CURSOR FOR 
SELECT related_id, Id
FROM Configuration
WHERE related_id IS NOT NULL

OPEN Crs
FETCH NEXT FROM Crs INTO @RELATED, @CURRENT_CONFIG
WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO TypeB(col)
    SELECT col
    FROM TypeA
    WHERE Id = @RELATED

    SET @CREATED = SCOPE_IDENTITY()

    UPDATE Configuration
    SET related_id = @CREATED
    WHERE Id = @CURRENT_CONFIG

    INSERT INTO ElementB (TypeB_id, Col1)
    SELECT @CREATED, Col1
    FROM ElementA
    WHERE TypeA_id = @RELATED

    DELETE ElementA
    WHERE TypeA_id = @RELATED

    DELETE TypeA
    WHERE Id = @RELATED

    FETCH NEXT FROM Crs INTO @RELATED, @CURRENT_CONFIG
END
DEALLOCATE Crs

你觉得在我的情况下可以消除光标吗?

2 个答案:

答案 0 :(得分:1)

您需要在此处使用输出子句来获取插入的identity_col(idcol)

我假设col的数据类型为varchar(50)。

        Create table #MyTable (idcol as int, col varchar(50));

            INSERT INTO TypeB
                        (col)
            OUTPUT INSERTED.identity_col --You need to relace identity_col with the actual identitycol.
                  ,INSERTED.col
                    INTO #MyTable
            SELECT col
            FROM   TypeA
            WHERE  Id IN(SELECT related_id
                         FROM   Configuration
                         WHERE  related_id IS NOT NULL)

--Add another column related_id in the temp table to get the original id

    ALTER TABLE #MyTable ADD related_id INT

    Update T
    set T.related_id=T1.id
    from #MyTable T
    JOIN TypeA T1
    on T.col= T1.col

            UPDATE A
            SET    a.related_id = B.idcol
            FROM   Configuration A
                    JOIN #MyTable B                
    ON B.related_id= A.related_id

        INSERT INTO ElementB (TypeB_id, Col1)
        SELECT distinct B.idcol, A.Col1
        FROM ElementA A 
        JOIN #MyTable B on A.TypeA_id= B.related_id

    DELETE ElementA
    WHERE  TypeA_id IN (SELECT distinct related_id
                        FROM   #MyTable)

    DELETE TypeA
    WHERE  Id IN (SELECT distinct related_id
                        FROM   #MyTable)

答案 1 :(得分:0)

我认为可以消除Cursor。试试这个。

INSERT INTO TypeB
            (col)
SELECT col
FROM   TypeA
WHERE  Id IN(SELECT related_id
             FROM   Configuration
             WHERE  related_id IS NOT NULL)

UPDATE A
SET    related_id = b.identity_col  -- replace identity_col with TypeB identity column name
FROM   Configuration A
       JOIN TypeB B
         ON a.Id = b.related_id

INSERT INTO ElementB
            (TypeB_id,Col1)
SELECT @CREATED,Col1
FROM   ElementA A
       JOIN TypeB B
         ON a.Id = a.TypeB_id
       JOIN (SELECT related_id
             FROM   Configuration
             WHERE  related_id IS NOT NULL) C
         ON A.TypeA_id = c.related_id 

DELETE ElementA
WHERE  TypeA_id IN (SELECT related_id
                    FROM   Configuration
                    WHERE  related_id IS NOT NULL)

DELETE TypeA
WHERE  Id IN (SELECT related_id
              FROM   Configuration
              WHERE  related_id IS NOT NULL)