如何使用CTE而不是Cursor

时间:2014-12-22 09:56:30

标签: cursor common-table-expression

我想在SQL Server 2012中使用公用表表达式(CTE)而不是Cursor。非常感谢您的帮助。

这是我的情况:

DECLARE
@tp_ID INTEGER

truncate table T_Rep_Exit_Checklist_Table

DECLARE cursorName CURSOR -- Declare cursor
LOCAL SCROLL STATIC

FOR

SELECT
tp_ID
from V_Rep_Exit_Checklist

OPEN cursorName -- open the cursor

FETCH NEXT FROM cursorName  INTO @tp_ID

WHILE @@FETCH_STATUS = 0

BEGIN

insert into T_Rep_Exit_Checklist_Table
SELECT
@tp_ID-- AS tp_ID
,Item_Status_Code
,Item_Status_Desc
,Item_Code
,Item_Desc
,Item_Cat_Code
,Item_Cat_Desc
,Item_Cleared_By_No
,Item_Cleared_By_Name
V_Rep_Exit_Checklist c


   FETCH NEXT FROM cursorName
    INTO @tp_ID
END

CLOSE cursorName -- close the cursor

DEALLOCATE cursorName -- Deallocate the cursor

1 个答案:

答案 0 :(得分:0)

关于您的查询的某些内容似乎没有意义。看起来像SELECT的INSERT语句缺少where子句,因此如果你的源视图有5条记录,你插入25条记录,因为你在第一次使用光标迭代时获取第一条记录的id,并插入所有具有该id的记录,然后对视图的每一行重复。

假设上述逻辑是有意的,那么你应该只需要一个CROSS JOIN:

INSERT T_Rep_Exit_Checklist_Table
    SELECT
        T1.tp_ID,
        T2.Item_Status_Code,
        T2.Item_Status_Desc,
        T2.Item_Code,
        T2.Item_Desc,
        T2.Item_Cat_Code,
        T2.Item_Cat_Desc,
        T2.Item_Cleared_By_No,
        T2.Item_Cleared_By_Name 
    FROM V_Rep_Exit_Checklist T1
        CROSS JOIN V_Rep_Exit_Checklist T2

但是,您希望将其视为CTE:

;WITH CTE AS (
    SELECT * FROM V_Rep_Exit_Checklist
)
INSERT T_Rep_Exit_Checklist_Table
    SELECT
        T1.tp_ID,
        T2.Item_Status_Code,
        T2.Item_Status_Desc,
        T2.Item_Code,
        T2.Item_Desc,
        T2.Item_Cat_Code,
        T2.Item_Cat_Desc,
        T2.Item_Cleared_By_No,
        T2.Item_Cleared_By_Name 
    FROM CTE T1
        CROSS JOIN CTE T2

如果我的假设是错误的,而你试图将视图中的所有记录直接插入到表中,那么为什么不只是简单的INSERT如下所示?

INSERT T_Rep_Exit_Checklist_Table
    SELECT
        tp_ID,
        Item_Status_Code,
        Item_Status_Desc,
        Item_Code,
        Item_Desc,
        Item_Cat_Code,
        Item_Cat_Desc,
        Item_Cleared_By_No,
        Item_Cleared_By_Name 
    FROM V_Rep_Exit_Checklist

但是,如果您的业务要求是一次只能从视图1 tp_ID插入记录,则可以使用while语句来替换光标:

DECLARE @Records TABLE (tp_ID INT)
INSERT @Records
    SELECT tp_ID FROM V_Rep_Exit_Checklist
DECLARE @tp_ID INTEGER
WHILE EXISTS (SELECT * FROM @Records) BEGIN
    SET @tp_ID = (SELECT TOP 1 tp_ID FROM @Records)
    INSERT T_Rep_Exit_Checklist_Table
        SELECT
            tp_ID,
            Item_Status_Code,
            Item_Status_Desc,
            Item_Code,
            Item_Desc,
            Item_Cat_Code,
            Item_Cat_Desc,
            Item_Cleared_By_No,
            Item_Cleared_By_Name 
        FROM V_Rep_Exit_Checklist
        WHERE tp_ID = @tp_ID
    DELETE @Records WHERE tp_ID = @tp_ID
END