2014-12-22 66 views
0

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

这是我的情况:

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 

回答

0

一些关于您的查询似乎没有什么意义。看起来你的INSERT语句在SELECT中缺少一个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