使用WHILE和游标的遍历操作

本文对比了使用游标和While循环在SQL中遍历数据的不同方法,详细介绍了如何通过While循环来替代游标实现相同的功能,并讨论了两种方法在性能上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         游标操作会锁住被遍历的表,容易引起死锁,应当尽量避免使用。

原游标代码:

    DECLARE @tbTargetPermissions    table(TargetPermissionId uniqueidentifier NOT NULL PRIMARY KEY)
    
INSERT INTO @tbTargetPermissions 
        
SELECT [TargetPermissionId] 
        
FROM [ps_RolePermissions] 
        
WHERE [TargetId] = @TargetId AND [RoleId] = @RoleId
    
    
DECLARE @TargetPermissionId uniqueidentifier;

    
--定义游标
    DECLARE TargetPermissions_ByRoleId_Cursor CURSOR FOR 
        
SELECT [TargetPermissionId] FROM @tbTargetPermissions 

    
--打开游标
    OPEN TargetPermissions_ByRoleId_Cursor

    
--读取游标第一条记录
    FETCH NEXT FROM    TargetPermissions_ByRoleId_Cursor INTO @TargetPermissionId

    
--检查@@FETCH_STATUS的值,以便进行循环读取
    WHILE @@FETCH_STATUS = 0
    
BEGIN
        
EXEC ps_TargetPermissionEntity_Select @TargetPermissionId;

        
FETCH NEXT FROM    TargetPermissions_ByRoleId_Cursor INTO @TargetPermissionId;
    
END

    
--关闭游标
    CLOSE TargetPermissions_ByRoleId_Cursor
    
DEALLOCATE TargetPermissions_ByRoleId_Cursor


改用While后仍然可以遍历执行存储过程 ps_TargetPermissionEntity_Select

    --把合符条件的目标权限Id加载到一个临时表变量中
    DECLARE @tbTargetPermissions    table(IndexId int IDENTITY (01NOT NULL PRIMARY KEY, TargetPermissionId uniqueidentifier NOT NULL)
    
INSERT INTO @tbTargetPermissions 
        
SELECT [TargetPermissionId] 
        
FROM [ps_RolePermissions] 
        
WHERE [TargetId] = @TargetId AND [RoleId] = @RoleId

    
DECLARE @MaxIndexId int;
    
SELECT  @MaxIndexId = MAX([IndexId]FROM @tbTargetPermissions--计算最大记录序号,用于遍历列表

    
WHILE @MaxIndexId > -1
    
BEGIN
        
DECLARE @TargetPermissionId uniqueidentifier;
        
SELECT @TargetPermissionId = [TargetPermissionId] FROM @tbTargetPermissions WHERE [IndexId] = @MaxIndexId;

        
EXEC ps_TargetPermissionEntity_Select @TargetPermissionId;

        
--删除最大记录项,重新判断记录项是否大于-1,以此判断是否遍历完列表
        DELETE @tbTargetPermissions WHERE [IndexId] = @MaxIndexId;
        
SELECT  @MaxIndexId = MAX([IndexId]FROM @tbTargetPermissions 
        
--SELECT @MaxIndexId--测试(倒序)
    END


执行效果相同,就是这里的while与上一方法的排序是相反的,如果对排序顺序有要求的,可以改变一下算法。
按顺序排列的代码如下:

    --把合符条件的目标权限Id加载到一个临时表变量中
    DECLARE @tbTargetPermissions    table(IndexId int IDENTITY (01NOT NULL PRIMARY KEY, TargetPermissionId uniqueidentifier NOT NULL)
    
INSERT INTO @tbTargetPermissions 
        
SELECT [TargetPermissionId] 
        
FROM [ps_RolePermissions] 
        
WHERE [TargetId] = @TargetId AND [RoleId] = @RoleId

    
DECLARE @MinIndexId int;
    
DECLARE @MaxIndexId int;
    
SELECT  @MinIndexId = MIN([IndexId]FROM @tbTargetPermissions--计算最小记录序号,用于遍历列表
    SELECT  @MaxIndexId = MAX([IndexId]FROM @tbTargetPermissions--计算最大记录序号,用于遍历列表

    
WHILE @MinIndexId <= @MaxIndexId
    
BEGIN
        
--SELECT @MinIndexId,@MaxIndexId--测试(顺序)
        DECLARE @TargetPermissionId uniqueidentifier;
        
SELECT @TargetPermissionId = [TargetPermissionId] FROM @tbTargetPermissions WHERE [IndexId] = @MinIndexId;

        
EXEC ps_TargetPermissionEntity_Select @TargetPermissionId;

        
--删除最小记录项,重新判断最小记录项是否小于等于最大记录项,以此判断是否遍历完列表
        DELETE @tbTargetPermissions WHERE [IndexId] = @MinIndexId;
        
SELECT  @MinIndexId = MIN([IndexId]FROM @tbTargetPermissions
    
END
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值