我早在SQL 7天前就知道一些性能原因,但同样的问题在SQL Server 2005中仍然存在吗?如果我在存储过程中有一个要单独操作的结果集,游标仍然是一个不好的选择吗?如果有,原因何在?
发布于 2008-09-12 02:00:00
因为游标会占用内存并创建锁。
您真正在做的是试图将基于集合的技术强加到基于非集合的功能中。而且,公平地说,我应该指出游标确实有用处,但它们不受欢迎,因为许多不习惯使用基于集合的解决方案的人使用游标,而不是找出基于集合的解决方案。
但是,当您打开游标时,您基本上是将这些行加载到内存中并锁定它们,从而创建潜在的块。然后,当您在游标中循环时,您正在对其他表进行更改,并且仍然保持游标的所有内存和锁处于打开状态。
所有这些都有可能导致其他用户的性能问题。
因此,作为一般规则,游标是不受欢迎的。特别是如果这是解决问题的第一个解决方案。
发布于 2010-06-11 23:53:30
上面关于SQL是一个基于集合的环境的评论都是正确的。但是,有时逐行操作很有用。考虑元数据和动态sql的组合。
举一个非常简单的例子,假设我在一个表中有100+记录,这些记录定义了我想要复制/截断/任何东西的表名。哪一个是最好的?对SQL进行硬编码以完成我需要做的事情?或者遍历这个结果集并使用dynamic-SQL (sp_executesql)来执行操作?
使用基于集合的SQL无法实现上述目标。
那么,要使用游标还是while循环(伪游标)?
只要使用正确的选项,SQL游标就可以:
INSENSITIVE将为您的结果集创建一个临时副本(使您不必为您的伪游标自己执行此操作)。
READ_ONLY将确保在底层结果集上没有锁。底层结果集中的更改将反映在后续的fetches中(就像从伪游标中获取TOP 1一样)。
FAST_FORWARD将创建一个优化的只进、只读游标。
在判定所有游标都是邪恶游标之前,请先阅读可用选项。
发布于 2011-07-21 05:12:25
有一个关于游标的变通方法,我每次需要时都会用到它。
我创建了一个表变量,其中包含一个identity列。
在其中插入我需要处理的所有数据。
然后使用计数器变量创建一个while块,并使用select语句从表变量中选择我想要的数据,其中标识列与计数器匹配。
这样我不会锁定任何东西,使用更少的内存,而且它很安全,我不会因为内存损坏或类似的东西而丢失任何东西。
并且区块代码易于查看和处理。
这是一个简单的例子:
DECLARE @TAB TABLE(ID INT IDENTITY, COLUMN1 VARCHAR(10), COLUMN2 VARCHAR(10))
DECLARE @COUNT INT,
@MAX INT,
@CONCAT VARCHAR(MAX),
@COLUMN1 VARCHAR(10),
@COLUMN2 VARCHAR(10)
SET @COUNT = 1
INSERT INTO @TAB VALUES('TE1S', 'TE21')
INSERT INTO @TAB VALUES('TE1S', 'TE22')
INSERT INTO @TAB VALUES('TE1S', 'TE23')
INSERT INTO @TAB VALUES('TE1S', 'TE24')
INSERT INTO @TAB VALUES('TE1S', 'TE25')
SELECT @MAX = @@IDENTITY
WHILE @COUNT <= @MAX BEGIN
SELECT @COLUMN1 = COLUMN1, @COLUMN2 = COLUMN2 FROM @TAB WHERE ID = @COUNT
IF @CONCAT IS NULL BEGIN
SET @CONCAT = ''
END ELSE BEGIN
SET @CONCAT = @CONCAT + ','
END
SET @CONCAT = @CONCAT + @COLUMN1 + @COLUMN2
SET @COUNT = @COUNT + 1
END
SELECT @CONCAThttps://stackoverflow.com/questions/58141
复制相似问题