2012-10-26 49 views
0

我正试图编写一个脚本,用于在我们的合并复制快照代理程序完成将快照应用于订户后恢复对存储过程的权限。这个SQL需要有些动态。SQL Server - 使用WHILE循环问题执行语句

目前,我正在选择我们所有存储过程的列表,并将它们与字符串语句一起插入到临时表中以用于“授予”权限。我试图遍历该表上的所有行,使用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

你不能说

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 
+0

谢谢......好奇的寿。进一步解释为什么我的SET @sqlrun =(SELECT ....)不被sql服务器接受?只是想了解,所以我不会再犯同样的错误,并遵循最佳实践。 – Encryption

+0

@Encryption - SQL Server中的变量是标量,它们只能包含单个数据类型的单个值。另一种方法是使用一个表变量,但在这种情况下,这并不会带给你任何地方。因此,您需要将三个值推入三个不同的变量,或者将它们连接起来,以便它们可以进入单个变量。 – MatBailie

+0

因此,使用SELECT @@ sql提供了一个字符串,其中SET @SQL没有提供字符串类型? – Encryption

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 
0

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

SELECT COUNT(*) FROM sqltemp 

的同时外:

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

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