SQL检查游标

时间:2017-04-05 14:47:47

标签: sql sql-server tsql cursor

我正在做一个返回一个roleIds表的select。 我正在寻找一种迭代值的方法,并为每个行值运行删除或(存储过程)。在尝试了许多不同的建议后,这就是我所拥有的:

BEGIN TRAN
DECLARE @RoleId bigint

DECLARE cur CURSOR FOR SELECT DISTINCT cr.RoleId
FROM ClientRole AS cr
INNER JOIN userRole AS ur ON cr.RoleId = ur.RoleId
AND cr.ClientId = 564564564

OPEN cur

FETCH NEXT FROM cur INTO @RoleId

WHILE @@FETCH_STATUS = 0 BEGIN

        --NEED TO CHECK IF RolePermissions ACTUALLY HAS THE PERMISSION
        DELETE  
        FROM RolePermissions
        WHERE RoleId = @RoleId
        AND PermissionId = 12341234

    FETCH NEXT FROM cur INTO @RoleId
END

CLOSE cur    
DEALLOCATE cur

ROLLBACK

目前在尝试"删除"是一个错误,因为它试图删除的行对于某些RoleId不存在。我试过If,WHILE,CASE但不确定我应该在这里做什么,因为我不知道如果它没有行就会传递RoleId。似乎游标不推荐,但是无法通过将其放在临时表中来完成同样的工作。

感谢任何建议

EDIT ::

最初我试图从游标运行存储过程: 最初我试图在每个roleId上运行存储过程:

    begin tran
    exec dbo.usp_DeleteRolePermission @RoleId = @RoleId,
    @PermissionId =  12341234,
    @PublishToCache = 1
commit

2 个答案:

答案 0 :(得分:2)

您可能不需要光标。像这样的单个语句可以很容易地转换为过程:

declare @ClientId     int = 564564564;
declare @PermissionId int = 12341234;

delete rp
from RolePermissions rp
where PermissionId = @PermissionId
  and exists (
    select 1
    from ClientRole as cr
      inner join userRole as ur 
        on cr.RoleId = ur.RoleId
      and cr.ClientId = @ClientId
      where ur.RoleId = rp.RoleId
      );

答案 1 :(得分:1)

从您的示例中不清楚为什么您实际需要迭代光标并单独删除每条记录。你不能发一个DELETE吗?

的一些东西
DELETE  
FROM RolePermissions
WHERE RoleId IN (SELECT cr.RoleId
                 FROM ClientRole AS cr
                 INNER JOIN userRole AS ur ON cr.RoleId = ur.RoleId
                 AND cr.ClientId = 564564564)
AND PermissionId = 12341234