【问题标题】:How to use while loop to iterate through each table name in SQL Server?如何使用 while 循环遍历 SQL Server 中的每个表名?
【发布时间】:2021-01-15 07:11:01
【问题描述】:

我正在使用动态 SQL(仍处于学习阶段),我被困在需要使用 WHILE 循环的部分:

  SET @tableName = (SELECT DISTINCT TableName FROM @dataStructure)

这里基本上我想确保@tableName(上面定义)中的所有表都应该发生while循环内的操作。我不知道如何将这个条件作为 while 循环的输入。

   WHILE()  #HOW CAN I PUT THE CONDITION HERE????
   BEGIN
       SET @str = ''
       SET @sqlstr = ''
    
       SELECT @table = TableName FROM @dataStructure
    
       SET @str = 'UPDATE a0' + char(13) + char(10)
                + ' SET a0.Mjolnir_Source_ID = CONCAT( ' 
    
    SELECT @str = @str + IIF(ReferenceTable  IS NULL, 'a0.' + columnName , alias + '.Mjolnir_Source_ID') + ',' 
                        FROM @dataStructure
                        WHERE TableName = @tableName AND ReferenceTable IS NOT NULL
                        ORDER BY columnName
    
    SELECT @str = @str + ') FROM ' + @table + ' a0'
    
    SELECT @sqlstr = @sqlstr +  +
                        + ' INNER JOIN ' + QUOTENAME(@U4SM_db_name) + '.dbo.' + QUOTENAME(ReferenceTable) + ' '  + alias + char(13) + char(10)
                        + ' ON a0.' + columnName + ' = ' + alias + '.' + ReferenceColumn + char(13) + char(10)
                        FROM @dataStructure 
                        WHERE TableName = @tableName AND ReferenceTable IS NOT NULL
                        ORDER BY columnPosition
    
    
    select @str + @sqlstr
    select @sqlstr
    SET @tableName = @tableName + 1
 END

谁能帮帮我?

【问题讨论】:

  • 就个人而言,我不会使用WHILE,而是会使用字符串聚合。你想在每张桌子上达到什么目标?
  • @Larnu 我有变量“@tableName”内的表列表,我只想对这些表执行以下操作。
  • 这并没有回答我提出的问题。您正在尝试执行的这项任务是做什么的?

标签: sql-server tsql while-loop


【解决方案1】:

以下是 WHILE 循环的示例。基本上,您获得第一个 TableName,然后如果它不是 NULL,则执行您的功能。然后获取下一个表名,并根据需要重复。

DECLARE @CurrentTableName nvarchar(100)
DECLARE @CustomSQL nvarchar(4000)

SET @CurrentTableName = (SELECT TOP 1 TableName FROM @dataStructure ORDER BY TableName)

WHILE @CurrentTableName IS NOT NULL
BEGIN
    SET @CustomSQL = 'SELECT TOP 10 * FROM ' + @CurrentTableName
    EXEC (@CustomSQL)
    SET @CurrentTableName = (SELECT TOP 1 TableName FROM @dataStructure WHERE TableName > @CurrentTableName ORDER BY TableName)
END

请注意,SQL 命令通常不能在关键点包含变量名(例如,SELECT * FROM @tableName)。相反,您将其保存为 SQL 字符串(我在上面称为 @CustomSQL),然后执行它(尽管在变量名周围加上括号)。

编辑:在生产之前先在测试站点上执行此操作,并知道“取消查询”按钮在哪里。 “获取下一行”部分没有正确编写,它只是在一个永久循环中运行,这种情况并不常见,但也不是未知的。

【讨论】:

  • 是的,我尝试实现它。但是我遇到的一个问题是,因为我想更新“@CurrentTableName”变量中的每个表,但它总是从中获取最后一条记录。我相信这与你提到的有关?比如“获得下一行”。知道我该如何解决吗?
  • 在选择“前 1”值时确保“排序依据”正确。另请注意,WHILE 循环中的语句也有一个 WHERE 子句来获取下一个值 (WHERE TableName &gt; @CurrentTableName)。确保这是正确的方式,而不是 >= 或 DB<>fiddle 两种方法注意我将EXEC更改为小提琴的PRINT。
  • PS 这是 imo 为什么游标通常更好的原因之一。通常在编写 WHERE 循环时,我首先编写循环逻辑而不使用任何处理逻辑 - 只是打印出任何变量集的当前值(例如,在这种情况下,@CurrentTableName)
  • 我不想使用第二种方法,因为它会从表中删除记录,我不想这样做。但是我使用了您的第一种方法,经过小幅修正后它起作用了。谢谢。
【解决方案2】:

使用 WHILE 获取光标。示例:

DECLARE myCursor CURSOR FOR  
    SELECT DISTINCT TableName FROM @dataStructure;
OPEN myCursor;  
FETCH NEXT FROM myCursor INTO @table:Name;  
WHILE @@FETCH_STATUS = 0  
   BEGIN  
      Print '   ' + @TableName 
      FETCH NEXT FROM myCursor INTO @TableName;  
   END;  
CLOSE myCursor;  
DEALLOCATE myCursor;  
GO 

【讨论】:

  • 就是这样。我想使用 While 循环而不是光标。
  • @astroluv 但是你的while循环只是一个更容易出错和更慢(通常)的游标版本。忽略基于集合的方法,游标通常更适合您。动态 sql 需要高级的 tsql 知识——而您还没有。尽可能简化。
【解决方案3】:

除非您需要更好的轮子,否则不要重新创建轮子:

sp_MSforeachtable

https://www.sqlshack.com/an-introduction-to-sp_msforeachtable-run-commands-iteratively-through-all-tables-in-a-database/

如果您担心在生产环境中使用可能会在未来发生变化的未记录过程,只需编写脚本并创建您自己的自定义命名版本。

【讨论】:

  • 我也打算发布这个 - 但是 a) 不清楚 OP 想要更新 every 表,或者甚至可以对每个表进行更新,并且 b ) 他们明确地想要做一个 WHILE 循环。
  • 您不必更新每个表。这就是 @whereand 参数 if 的用途:“默认情况下,sp_MSforeachtable 应用于数据库中的所有用户表。使用此参数过滤您要使用的表。在下一节中,我将解释如何过滤表”。 OP 可以轻松地从他们拥有的数据源中传递表名。
  • 我也没有,直到我在试图回答这个问题时查了一下。 xD 你也可以使用 ?查询中的占位符以过滤表。您传递给@command 的查询字符串将替换每次出现的 ?使用正在运行查询的表的名称。所以你可以写一个类似DELETE FROM ? WHERE '?' IN ('TableIWantToDelete', 'OtherTableIWantToDelete', 'TableIReallyHate')的查询
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-24
  • 2020-06-22
  • 2021-11-29
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多