SQL Server 2008 是否有更有效的方法来执行此更新循环?



第一个发布的问题,对于任何错误,我提前道歉。 该表包含分配给团队的记录,初始分配是通过另一个流程完成的。通常,我们必须重新分配座席的记录,并将其平均分配给团队的其他成员。我们一直在手工做,一个接一个,这很麻烦。所以我想出了这个解决方案:

DECLARE @UpdtAgt TABLE (ID INT, Name varchar(25))
INSERT INTO @UpdtAgt
VALUES (1, 'Gandalf')
,(2,'Hank')
,(3,'Icarus')

CREATE TABLE #UpdtQry (TblID varchar(25))
INSERT INTO #UpdtQry
SELECT ShtID
FROM TestUpdate
DECLARE @RowID INT
DECLARE @AgtID INT
DECLARE @Agt varchar(25)
DECLARE @MaxID INT
SET @MaxID = (SELECT COUNT(*) FROM @UpdtAgt)
SET @AgtID = 1
--WHILE ((SELECT COUNT(*) FROM #UpdtQry) > 0)
WHILE EXISTS (SELECT TblID FROM #UpdtQry)
BEGIN
SET @RowID = (SELECT TOP 1 TblID FROM #UpdtQry)
SET @Agt = (SELECT Name FROM @UpdtAgt WHERE ID = @AgtID)
UPDATE TestUpdate
SET Assignment = @Agt
WHERE ShtID = @RowID
DELETE #UpdtQry WHERE TblID = @RowID
IF @AgtID < @MaxID
SET @AgtID = @AgtID + 1
ELSE 
SET @AgtID = 1

END
DROP TABLE #UpdtQry

这真的是我第一次尝试做这么深入的事情。更新 100 行大约需要 30 秒。UPDATE 表 TestUpdate 只有聚集索引。如何提高工作效率?

编辑:我在解释中没有很好地定义@UpdtAgt和 #UpdtQry 表。 @UpdtAgt将保存正在重新分配记录的代理,并且每次使用时都可能会更改。 #UpdtQry 将有一个 WHERE 子句来定义将重新分配哪些代理记录,同样,这将随着每次使用而更改。我希望这使这一点更加清楚。再次,为第一次没有做对而道歉。

编辑2:我注释掉了旧的WHILE子句,并插入了HABO建议的子句。再次感谢哈博。

我认为这就是你要找的:

DECLARE @UpdtAgt TABLE 
(
ID INT, 
Name VARCHAR(25)
)
INSERT @UpdtAgt
VALUES (1, 'Gandalf')
,(2, 'Hank')
,(3, 'Icarus')
UPDATE t
SET t.Assignment = a.Name
FROM TestUpdate AS t
INNER JOIN @UpdtAgt AS a
ON t.ShtID = a.ID

这应该一次完成所有 4 行。

附言...

如果您将来确实像原始帖子一样创建表,请尝试保持列和变量的命名与其目的一致!

在你的例子中,你使用了IDAgtIDShtID和(最令人困惑的)TblID(我认为它们都是一回事?[如果我错了,请纠正我!如果你到处都称呼它AgtID(变量@AgtID[不需要@RowID]),那么一目了然就会容易得多!同样的事情也适用于AssignmentName.

因为这是你第一次尝试这样的事情,所以我想祝贺你做了一些有效的事情。虽然它不理想(是什么?),但它满足了主要目标:它有效。有一种更好的方法可以使用称为光标的东西来执行此操作。我使用Microsoft的以下页面提醒自己正确的语法:单击此处获取有关光标的完整说明

话虽如此,本文末尾的代码显示了我对您的情况的快速解决方案。请注意以下事项:

  1. 定义@TestUpdate表,以便查询将在 MSSQL 中运行,而无需使用永久表。
  2. 只需将@UpdtAgt表设置为临时表。但是,如果经常使用它,最好将其设置为永久表。
  3. 最后的CLOSEDEALLOCATE陈述很重要——忘记这些会产生相当不愉快的后果。
DECLARE @TestUpdate TABLE (ShtID int, Assignment varchar(25))
INSERT INTO @TestUpdate
VALUES (1,'Fred')
,(2,'Barney')
,(3,'Fred')
,(4,'Wilma')
,(5,'Betty'),(6,'Leopold'),(7,'Frank'),(8,'Fred')
DECLARE @UpdtAgt TABLE (ID INT, Name varchar(25))
INSERT INTO @UpdtAgt
VALUES (1, 'Gandalf')
,(2,'Hank')
,(3,'Icarus')
DECLARE @recid int
DECLARE @AgtID int SET @AgtID=0
DECLARE @MaxID int SET @MaxID = (SELECT COUNT(*) FROM @UpdtAgt)
DECLARE assignment_cursor CURSOR
FOR SELECT ShtID FROM @TestUpdate
OPEN assignment_cursor
FETCH NEXT FROM assignment_cursor
INTO @recid
WHILE @@FETCH_STATUS = 0
BEGIN
SET @AgtID = @AgtID + 1
IF @AgtID > @MaxID SET @AgtID = 1
UPDATE @TestUpdate
SET Assignment = (SELECT TOP 1 Name FROM @UpdtAgt WHERE ID=@AgtID)
FROM @TestUpdate TU   
WHERE ShtID=@recid
FETCH NEXT FROM assignment_cursor INTO @recid
END
CLOSE assignment_cursor
DEALLOCATE assignment_cursor
SELECT * FROM @TestUpdate

最新更新