SQL Server使用游标或临时表遍历数据

方法一:使用游标(此方法适用所有情况,对标结构没有特殊要求。)

declare @ProductName nvarchar(50)
declare pcurr cursor for select ProductName from Products
open pcurr
fetch next from pcurr into @ProductName
while (@@fetch_status = 0)
begin
 print (@ProductName)
 fetch next from pcurr into @ProductName
end
close pcurr
deallocate pcurr  

--给空的sort进行赋值 从1开始按顺序排
declare @id int declare cursor1 cursor for
select ClassId from [content] group by ClassId
open cursor1
fetch next from cursor1 into @id
while @@fetch_status=0
begin
select ROW_NUMBER()over(order by id) as pid,id into #ttttt from [content] where classid=@id;
update [content] set sort = pid from #ttttt where #ttttt.id = [content].id;
drop table #ttttt;
fetch next from cursor1 into @id
end close cursor1

在关系数据库中,我们对于查询的思考是面向集合的。而游标打破了这一规则,游标使得我们思考方式变为逐行进行.

对于游标一些优化建议

  •      如果能不用游标,尽量不要使用游标
  •      用完用完之后一定要关闭和释放
  •      尽量不要在大量数据上定义游标
  •      尽量不要使用游标上更新数据
  •      尽量不要使用insensitive, static和keyset这些参数定义游标
  •      如果可以,尽量使用FAST_FORWARD关键字定义游标
  •      如果只对数据进行读取,当读取时只用到FETCH NEXT选项,则最好使用FORWARD_ONLY参数
  • 参考:http://www.cnblogs.com/moss_tan_jun/archive/2011/11/26/2263988.html

方法二:使用循环(此方法适用于表带有自动增加标识的字段)

declare @ProductName nvarchar(50)
declare @ProductID int
select @ProductID=min(ProductID) from Products
while @ProductID is not null
begin
 select @ProductName=ProductName from Products where
ProductID=@ProductID
 print(@ProductName);
 select @ProductID=min(ProductID) from Products where
ProductID>@ProductID
end

 

--删除临时表#Tmp
create table #Tmp  --创建临时表#Tmp
(
    ID   int IDENTITY (1,1)     not null, --创建列ID,并且每次新增一条记录就会加1
    WokNo                varchar(50),   
    primary key (ID)      --定义ID为临时表#Tmp的主键      
);

--declare @temp table   
--(   
--   [id] int IDENTITY(1,1),   
--   [Name] varchar(10)   
--)   

Select * from #Tmp    --查询临时表的数据
truncate table #Tmp  --清空临时表的所有数据和约束
相关例子:
Declare @Wokno Varchar(500)  --用来记录职工号
Declare @Str NVarchar(4000)  --用来存放查询语句
Declare @Count int  --求出总记录数      
Declare @i int
Set @i = 0 
Select @Count = Count(Distinct(Wokno)) from #Tmp
While @i < @Count 
    Begin
       Set @Str = 'Select top 1 @Wokno = WokNo from #Tmp Where id not in (Select top ' + Str(@i) + 'id from #Tmp)'
       Exec Sp_ExecuteSql @Str,N'@WokNo Varchar(500) OutPut',@WokNo Output
       Select @WokNo,@i  --一行一行把职工号显示出来
       Set @i = @i + 1
    End

--drop table #temp

 

USE Test_DBData;
GO
--修正表中REC_CreateBy,REC_ModifyBy
CREATE TABLE #temp
    (
      id INT IDENTITY(1, 1) ,
      tablename NVARCHAR(100)
    );
DECLARE @tablename NVARCHAR(100);
DECLARE @n INT;
DECLARE @count INT;
DECLARE @str NVARCHAR(4000);
  --用来存放查询语句
DECLARE @tableCreateBy NVARCHAR(150);
DECLARE @tableModifyBy NVARCHAR(150);
SELECT  @n = 1;
INSERT  #temp
        ( tablename
        )
        SELECT  name
        FROM    sysobjects
     WHERE type = 'U '
     AND (name <> 'Dim_Employee')
     AND (name <> 'Fct_ChannelType')
    AND (name <> 'Rel_TPOCommodityMessage')
    
AND (name LIKE 'Dim%' OR name LIKE 'Fct%' OR name LIKE 'Rel%');
SELECT  @count = @@rowcount;
WHILE @n <= @count
    BEGIN
        SELECT  @tablename = ( SELECT   tablename
                               FROM     #temp
                               WHERE    id = @n
                             );
        SET @tableCreateBy = @tablename + '.REC_CreateBy';
        SET @tableModifyBy = @tablename + '.REC_ModifyBy';
        SET @str = 'IF EXISTS ( SELECT  *
            FROM    ( SELECT    '+@tableCreateBy+' 
                      FROM      '+@tablename+'
                                INNER JOIN dbo.Dim_Employee ON '+@tableCreateBy+' = Dim_Employee.LoginName
                    ) tb)
    BEGIN
        UPDATE  '+@tablename+'
        SET     REC_CreateBy = Dim_Employee.EmployeeId
        FROM    '+@tablename+'
                INNER JOIN dbo.Dim_Employee ON '+@tableCreateBy+' = Dim_Employee.LoginName;
    END;    
    IF EXISTS ( SELECT  *
            FROM    ( SELECT    '+@tableModifyBy+'
                      FROM      '+@tablename+'
                                INNER JOIN dbo.Dim_Employee ON '+@tableModifyBy+' = Dim_Employee.LoginName
                    ) tb )
    BEGIN
        UPDATE  '+@tablename+'
        SET     REC_ModifyBy = Dim_Employee.EmployeeId
        FROM    '+@tablename+'
                INNER JOIN dbo.Dim_Employee ON '+@tableModifyBy+' = Dim_Employee.LoginName;
    END;    
    ';
        EXEC(@str);
        SELECT  @n = @n + 1;
        DELETE  FROM #temp
        WHERE   tablename = @tablename;
    END;
--删除临时表
IF OBJECT_ID(N'tempdb.dbo.#temp') IS NOT NULL
    BEGIN
        DROP TABLE #temp;
    END

 

1.分批更新数据库
declare @x int
set @x=1 
while(@x<=51) 
begin 
begin tran 
update UserFavorite set UserFavorite.firstpublishtime = product.lastpublishtime
from UserFavorite,product where UserFavorite.productid = product.id 
and UserFavorite.id between (@x-1)* 10000 and @x*10000
commit tran
set @x=@x+1 
WAITFOR DELAY '00:00:30'; --等待5秒
end

 

 

 

转载于:https://www.cnblogs.com/shy1766IT/p/5562618.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值