【问题标题】:Replacing a cursor with apply to loop through all tables in a database用 apply 替换游标以遍历数据库中的所有表
【发布时间】:2013-07-31 10:29:19
【问题描述】:

我有一组 (100+) 个表,所有表都包含两个字段

RowChanged bit
ChangedFields bit

现在,发生了一个错误,当 ChangedFields 为空时,一些条目的 RowChanged = 1。因此,我需要检查这些并将 RowChanged = 0 设置为 ChangedFields 为空。

我通过以下光标实现了这一点。


BEGIN TRANSACTION
USE DatabaseName --Database name to clean

DECLARE @Table_Name VARCHAR(50)
DECLARE @Query VARCHAR(250)
DECLARE Table_Cursor CURSOR FOR SELECT Name FROM sys.tables;
DECLARE @Affected_Rows INTEGER = 0

OPEN Table_Cursor
FETCH NEXT FROM Table_Cursor INTO @Table_Name
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @Query = 'Update '+@Table_Name+' Set RowChanged = 0 Where RowChanged = 1 And (LEN(RTRIM(CONVERT(NVARCHAR(100), ChangedFields))) = 0 OR ChangedFields IS NULL)'
    EXEC (@Query)
    SET @Affected_Rows = @Affected_Rows + COALESCE(@@ROWCOUNT, 0)
    FETCH NEXT FROM Table_Cursor INTO @Table_Name
END
SELECT @Affected_Rows AS Affected_Rows

CLOSE  Table_Cursor
DEALLOCATE Table_Cursor

ROLLBACK --Change to COMMIT in order to save changes

虽然这确实有效,但我对使用光标有一种基因厌恶。此外,我刚刚了解到 Apply 在许多情况下可以实现 Cursors 在 2005 年之前所做的事情。

我需要做的是检查数据库中的所有表并检查 RowChanged = 1 和 ChangedFields (如 '' 或 NULL )的条件。

我尝试过使用 TVF 解决这个问题,但我一直在做空。虽然我可以在单个表中执行操作,但从 sys.tables 获取列表并在多个表中执行某些操作却让我望而却步。

【问题讨论】:

    标签: sql foreach cursor


    【解决方案1】:

    您可以用while循环语句替换光标。尝试使用如下语句来实现所需的 o/p。

    select name into #table from sys.tables
    while (select count(*) from #table)>0
    begin
        set rowcount 1  
        select @Table_Name = name from sys.tables
        set rowcount 0  
        .......
        .......
    
        delete from #table where name = @Table_Name
    end
    

    上面的 sn-p 来自 sybase,你可能需要对语法做一些小的修改。我希望这会有所帮助。

    【讨论】:

      【解决方案2】:
      declare @stmt nvarchar(max)
      
      select
         @stmt =
            isnull(@stmt + nchar(13) + nchar(10), '') + 
            'update '+ name +' set RowChanged = 0 Where RowChanged = 1 And (LEN(RTRIM(CONVERT(NVARCHAR(100), ChangedFields))) = 0 OR ChangedFields IS NULL)'
      from sys.tables
      
      print @stmt
      
      sp_executesql @stmt = @stmt
      

      还有未记录的存储过程sp_MSforeachtable - SQL Server sp_msforeachtable usage to select only those tables which meet some condition。实际上,我在工作中从未使用过它,所以仅供参考。

      【讨论】:

      • 我被警告不要使用sp_MSforeachtable,当数据库中有很多表时,您似乎无法信任它。
      • 更改了答案 - 我从未在工作中使用过它,但听说过它,所以我认为提及它会很好。我更喜欢动态 SQL,因为恕我直言,它维护起来更简单,而且我总是可以打印语句来查看我将执行什么
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多