SQL Server - 使用WHILE循环问题执行语句

时间:2012-10-26 15:24:10

标签: sql sql-server

我正在尝试编写一个脚本,在我们的合并复制快照代理完成将快照应用于订阅者之后,该脚本可用于恢复存储过程的权限。这个SQL需要有点动态。

目前,我正在选择所有存储过程的列表,并将它们与“授予”权限的字符串语句一起插入临时表中。我试图遍历该表上的所有行,使用EXEC()命令逐个执行语句。我一直收到错误

  

当未使用EXISTS引入子查询时,只能在选择列表中指定一个表达式

但我的SQL语句看起来应该没问题。也许我不明白WHILE在SQL Server中是如何工作的。

这是我的代码:

BEGIN
CREATE TABLE sqltemp (id int IDENTITY(1, 1) , Stmt1 varchar(max), Stmt2 varchar(max),  Stmt3 varchar(max))

INSERT INTO sqltemp 
   SELECT 
      'GRANT EXECUTE ON OBJECT::' as Stmt1, name as Stmt2, 'TO edoc_only_execute' as Stmt3
   FROM sys.sysobjects
   WHERE 
      type = 'P' AND name NOT LIKE 'MSMerge%'

DECLARE @counter int = 1
WHILE (@counter < (SELECT COUNT(*) FROM sqltemp))
BEGIN
    DECLARE @sqlrun varchar(max)
    SET @sqlrun = (SELECT Stmt1, Stmt2, Stmt3 FROM sqltemp WHERE id = @counter)
    EXEC(@sqlrun)
    SET @counter = @counter + 1
END
END
GO
DROP TABLE sqltemp

两个问题:

  1. 如何为临时表中的每个项目完成上述脚本的执行?

  2. 在应用快照后,是否有更好的方法来编写脚本来恢复数据库中每个存储过程的权限(注意:我必须能够使用SQL系统表来提取存储过程名称)?

3 个答案:

答案 0 :(得分:3)

你不能说

SET @sqlrun = (SELECT Stmt1, Stmt2, Stmt3 FROM sqltemp WHERE id = @counter)

你必须连接它们

SELECT @sqlrun = Stmt1 +' '+ Stmt2 +' '+ Stmt3 FROM sqltemp WHERE id = @counter

更好的解决方案可能是?

GRANT EXEC TO edoc_only_execute

答案 1 :(得分:2)

更正了第一个问题的查询

    BEGIN
    CREATE TABLE sqltemp (id int IDENTITY(1, 1) , Stmt1 varchar(max), Stmt2 varchar(max),  Stmt3 varchar(max))

    INSERT INTO sqltemp SELECT 'GRANT EXECUTE ON OBJECT::' as Stmt1, name as Stmt2, 'TO edoc_only_execute' as Stmt3
                        FROM sys.sysobjects
                        WHERE type = 'P' AND name NOT LIKE 'MSMerge%'

    DECLARE @counter int = 1
    WHILE (@counter < (SELECT COUNT(*) FROM sqltemp))
    BEGIN
        DECLARE @sqlrun varchar(max)
        SELECT @sqlrun = Stmt1 + Stmt2 +' '+ Stmt3 FROM sqltemp WHERE id = @counter
        PRINT @sqlrun
        EXEC(@sqlrun)
        SET @counter = @counter + 1
    END
    END

答案 2 :(得分:0)

@ 010001100110000101110010011010和@podiluska打败了我,但是......

SELECT COUNT(*) FROM sqltemp

在外面:

SET @end = SELECT COUNT(*) FROM sqltemp
WHILE (@counter < @end)
    ...

无需为每个循环迭代重新计算结束条件。