【问题标题】:SQL Server - Execute statements using WHILE Loop IssuesSQL Server - 使用 WHILE 循环问题执行语句
【发布时间】:2012-10-26 15:24:10
【问题描述】:

我正在尝试编写一个脚本,该脚本可用于在我们的合并复制快照代理完成将快照应用于订阅者后恢复对存储过程的权限。这个 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 系统表来提取存储过程名称)?

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    你不能说

    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
    

    【讨论】:

    • 谢谢...很好奇。进一步解释为什么我的 SET @sqlrun = (SELECT ....) 不能被 sql server 接受?只是想了解,所以我不会再犯同样的错误,并遵循最佳实践。
    • @Encryption - SQL Server 中的变量是标量,它们只能包含单一数据类型的单一值。另一种方法是使用表变量,但在这种情况下,这并不能帮助您。因此,您要么需要将这三个值推送到三个不同的变量中,要么将它们连接起来,以便它们可以进入一个变量。
    • 所以使用 SELECT @@sql 提供了一个字符串,而 SET @SQL 没有提供字符串类型?
    【解决方案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
    

    【讨论】:

      【解决方案3】:

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

      SELECT COUNT(*) FROM sqltemp
      

      在这段时间之外:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-31
        • 2011-05-28
        • 2016-01-04
        • 2018-05-27
        • 1970-01-01
        • 1970-01-01
        • 2021-07-25
        相关资源
        最近更新 更多