sql-server - 游标是执行此类操作的唯一选择吗

标签 sql-server sql-server-2008 database-cursor

我正在尝试优化一个长事务,并且我发现以下操作已经完成了很多次:

Declare @myCursor CURSOR FAST_FORWARD FOR
SELECT field1, MIN(COALESCE(field2, -2)) FROM MyTable tempfact
LEFT JOIN MyTable sd
ON tempfact.ID = sd.ID AND sd.TransactionId = @transactionId
WHERE tempfact.SomeField IS NULL
AND tempfact.TransactionId = @transactionId
GROUP BY tempfact.field1

OPEN @myCursor

FETCH NEXT FROM @myCursor INTO @field1Variable, @field2Variable

WHILE @@FETCH_STATUS = 0
BEGIN
   EXEC USP_SOME_PROC @field1Variable, @field2Variable
   FETCH NEXT FROM @myCursor INTO @field1Variable, @field2Variable
END

CLOSE @myCursor
DEALLOCATE @myCursor

USP_SOME_PROC 存储过程的代码如下:

IF NOT EXISTS (SELECT * FROM SomeTable WHERE Field1 = @field1)
BEGIN
   INSERT INTO SomeTable (Field1, Field2)
   VALUES (@field1, @field2)
END

就像我提到的,这是在很多地方完成的,涉及的表和字段不同,但想法保持不变,并且我确信如果游标不存在,可能有一种方法可以提高这些存储过程的性能使用并且可能通过使此事务更快,我们遇到的死锁问题(另一篇文章的主题)可能会得到解决。

最佳答案

您可以使用MERGE来实现此目的

;WITH Source AS
(
SELECT field1,
       MIN(COALESCE(field2, -2)) as field2
FROM   MyTable tempfact
       LEFT JOIN MyTable sd
         ON tempfact.ID = sd.ID
            AND sd.TransactionId = @transactionId
WHERE  tempfact.SomeField IS NULL
       AND tempfact.TransactionId = @transactionId
GROUP  BY tempfact.field1  
)
MERGE SomeTable AS T
USING Source S
ON (T.Field1 = S.Field1)


WHEN NOT MATCHED BY TARGET THEN
    INSERT (Field1, Field2)
    VALUES (field1, field2)
    ;

关于sql-server - 游标是执行此类操作的唯一选择吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7502360/

相关文章:

SQL Server 竞态条件问题

sql-server - 从 Azure BACPAC 恢复数据库出现错误

c# - Entity Framework 迁移模型优先

sql - 没有返回任何行的情况下使用COALESCE

python - 为什么在 Python 中关闭 Sqlite3 的游标

postgresql - 在 PostgreSQL 9.2 中更新数据库行而不锁定表

sql-server - 如何在存储过程中设置锁?

sql-server-2008 - 如何解决 Reporting Services 的错误

mysql - 使用多个连接优化查询

c# - DataReader 光标倒带