SQL-慢While循环

时间:2018-08-20 16:19:02

标签: sql sql-server

我有以下T-SQL代码,它们一次向临时表添加或更新1条记录。有没有人建议加快这个过程?

DECLARE @Total AS INT

SELECT @Total = count(AgentsID) from #TempAgentsConcat

DECLARE @counter AS INT
SET @counter = 1

DECLARE @CurrentVal AS NVARCHAR(1024)
DECLARE @RowCount AS INT
DECLARE @OBJ_ID AS INT

while (@counter <= @Total)
  begin
    SELECT @OBJ_ID = Id FROM #TempAgentsConcat WHERE AgentsId = @counter
    SELECT @CurrentVal = SVRMachine FROM #TempAgentsConcat WHERE ID = @OBJ_ID
    IF EXISTS (SELECT * FROM #TempEndpoints WHERE ID = @OBJ_ID)
        BEGIN
            UPDATE #TempEndpoints SET SVRMachine = @CurrentVal WHERE ID = @OBJ_ID
        END
    ELSE
        BEGIN
            INSERT INTO #TempEndpoints (SVRMachine, IPPort, ID)
            VALUES (@CurrentVal, NULL, @OBJ_ID)
        END
    --END

    SET @counter = @counter + 1
  end

2 个答案:

答案 0 :(得分:1)

您似乎正在尝试将一个表合并到另一个表中。首先,让我们谈谈您的查询中的几个问题- 1.除非非常必要,否则避免使用循环。 2.通过在2个查询中读取同一行来分配两个不同的变量。 您可以在单个查询中完成此操作,例如

SELECT @OBJ_ID = Id,@CurrentVal = SVRMachine FROM #TempAgentsConcat WHERE AgentsId = @counter

代替2个查询

SELECT @OBJ_ID = Id FROM #TempAgentsConcat WHERE AgentsId = @counter
SELECT @CurrentVal = SVRMachine FROM #TempAgentsConcat WHERE ID = @OBJ_ID

我们不使用循环就重写查询。 @Cetin的答案是解决方案之一。您的需求看起来是合并表的经典示例,因此您可以使用SQL MERGE(SQL Server 2008及更高版本)。您可以阅读有关MERGEhere的更多信息,请查看示例“ C”。

使用MERGE,您的查询如下所示。

MERGE INTO #TempEndpoints AS Target  
USING (SELECT SVRMachine , Id from #TempAgentsConcat)  
       AS Source (SVRMachine, ID)  
ON Target.ID = Source.ID  
WHEN MATCHED THEN  
  UPDATE SET SVRMachine = Source.SVRMachine  
WHEN NOT MATCHED BY TARGET THEN  
  INSERT (ID, IPPort, SVRMachine) VALUES (Id, NULL,SVRMachine)

答案 1 :(得分:0)

为什么要使用很多变量并循环。 SQL Server(也包括任何SQL系列数据库)最适合使用集合而不是循环:

UPDATE #TempEndpoints
SET SVRMachine = ac.SVRMachine
FROM #TempAgentsConcat ac
WHERE #TempEndpoints.Id = ac.ID;

INSERT INTO #TempEndpoints
(
    SVRMachine,
    ID
)
SELECT SVRMachine,
       ID
FROM #TempAgentsConcat ac
WHERE NOT EXISTS
(
    SELECT * FROM #TempEndpoints ep WHERE ep.ID = ac.ID
);