首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

[原] 游标替代解决办法

2012-01-09 
[原] 游标替代我一直反对使用游标,游标在SQL定义成面向过程,这与SQL的面向集合感觉有点不符。而且,游标会引

[原] 游标替代
我一直反对使用游标,游标在SQL定义成面向过程,这与SQL的面向集合感觉有点不符。而且,游标会引起很多性能,资源问题。我前几天查了一下我们的数据库服务器。一共搜出将近一百个用了游标存储过程,更要命的是:游标竟然没有 Close,也没有 DEALLOCATE。俺头大了,俺这个非专职的临时DBA也管不了这么多,全找出来,让他们自行改吧。
俺这临时DBA没有权力,但有些东东,还得龟腚一下。以后严禁使用游标。不让用,得有个替代的办法吧。这个方法别人用了N年,俺也用了N年,CSDN的贴子里也贴了N年,俺再多贴一次,也未不可。

-----------------------
-- 查找未关闭的游标。
-----------------------
CREATE TABLE ##游标 ( Var_DBName VarChar(255),Var_ProcName VarChar(255) );
DECLARE @Var_DbNaem VarChar(255);
DECLARE @NVr_Cmd NVarChar(4000);

SELECT @Var_DbNaem=MIN([NAME]) from master..sysdatabases

WHILE NOT @Var_DbNaem IS NULL BEGIN
SET @NVr_Cmd='
INSERT INTO ##游标(Var_ProcName,Var_DBName)
SELECT distinct 名称,''' +@Var_DbNaem + '''
FROM (
select 
b.Name as 名称
,a.Name as 参数
,c.Text as 语句
from 
[' +@Var_DbNaem + '].DBO.syscolumns a
left join
[' +@Var_DbNaem + '].DBO.sysobjects b on a.ID=b.ID
join
[' +@Var_DbNaem + '].DBO.syscomments c on c.ID=b.ID
where
b.xtype in(''FN'',''IF'',''TF'',''P'') AND C.TEXT LIKE ''%CURSOR%'' AND (NOT C.TEXT LIKE ''%DEALLOCATE%'')
) AS T'

PRINT @NVR_CMD

EXECUTE(@NVR_CMD);
SELECT @Var_DbNaem=MIN([NAME]) from master..sysdatabases WHERE [NAME]>@Var_DbNaem
END

SELECT * FROM ##游标
DROP TABLE ##游标

GO

SQL code
USE TESTGOCREATE TABLE LX1(INT_I INT,VAR_A VARCHAR(32),VAR_B VARCHAR(32))GOINSERT INTO LX1 VALUES(1,'A','E')INSERT INTO LX1 VALUES(2,'B','F')INSERT INTO LX1 VALUES(3,'C','G')INSERT INTO LX1 VALUES(4,'D','H')GO-----------------------------原表能确定唯一的单一主键。--如果是多主键,可以在表变量中添加自增字段(IDENTITY)或字符型的组合字段( KEY1 + '|' + KEY2 + '| + KEY3 ... ) 。---------------------------DECLARE @INT_I INTDECLARE @VAR_A VARCHAR(32)DECLARE @VAR_B VARCHAR(32)DECLARE @TAB_LX TABLE (INT_I INT,VAR_A VARCHAR(32),VAR_B VARCHAR(32))INSERT INTO @TAB_LX SELECT * FROM LX1SELECT @INT_I=MIN(INT_I) FROM @TAB_LXWHILE NOT @INT_I IS NULL BEGIN    SELECT @VAR_A=VAR_A,@VAR_B=VAR_B FROM @TAB_LX WHERE INT_I=@INT_I        --提取值    PRINT @VAR_A + '   '  + @VAR_B        SELECT @INT_I=MIN(INT_I) FROM LX1 WHERE INT_I>@INT_IENDGO-----------------------------原表没有唯一主键--可在表变量中添加一个自增编号。---------------------------DECLARE @INT_ID INTDECLARE @VAR_A VARCHAR(32)DECLARE @VAR_B VARCHAR(32)DECLARE @TAB_LX TABLE (INT_ID INT IDENTITY(1,1) ,INT_I INT,VAR_A VARCHAR(32),VAR_B VARCHAR(32))INSERT INTO @TAB_LX (INT_I,VAR_A,VAR_B) SELECT * FROM LX1SELECT @INT_ID=MIN(INT_ID) FROM @TAB_LXWHILE NOT @INT_ID IS NULL BEGIN    SELECT @VAR_A=VAR_A,@VAR_B=VAR_B FROM @TAB_LX WHERE INT_ID=@INT_ID        ---提取值。    PRINT @VAR_A + '   '  + @VAR_B        SELECT @INT_ID=MIN(INT_ID) FROM @TAB_LX WHERE INT_ID>@INT_IDENDGO


[解决办法]
学习!
[解决办法]
探讨
学习!

[解决办法]
mark,
也不能一概而轮,毕竟cursor还是有其存在的必要性的,
有些时候cursor还是很好用的。。。。。。
[解决办法]
不错
[解决办法]
游标会引起很多性能
[解决办法]
探讨
mark,
也不能一概而轮,毕竟cursor还是有其存在的必要性的,
有些时候cursor还是很好用的。。。。。。

[解决办法]
关于游标csdn这好像讨论过,不过想用好它,肯定要先了解它的用法和原理!
------解决方案--------------------


学习。
[解决办法]

探讨
mark,
也不能一概而轮,毕竟cursor还是有其存在的必要性的,
有些时候cursor还是很好用的。。。。。。

[解决办法]
"严谨使用游标"-->"避免使用游标"

话有时不能说得太死。

根据实际情况,游标有许多替代方案:
1.联表
2.动态sql
3.临时表
4.循环
……

热点排行