查看SQL Server 2012上所有数据库中的截断表

时间:2015-12-04 12:19:55

标签: sql-server tsql sql-server-2012 truncate

我正在开发一个专注于服务器中截断表的项目。该项目的目标是在审计表中记录所有截断的表。我已经在下面编写了一个在单个数据库上工作正常的代码;但是,我无法在所有数据库上自动运行该代码。我试过写:

  1. 光标
  2. 在存储过程中使用Exec ('Use ' + @DatabaseName + ';')
  3. 执行sp_MSforeachDB和存储过程。
  4. 每次尝试为所有数据库运行sproc时,都会在代码存在的数据库上执行。如何在所有数据库上执行它。

    主要查询:

    DBCC TRACEON (2537) -- All Log Files
    
    ;WITH  TranCte as ( SELECT
            [Transaction Id]
            ,[Transaction Name]
            ,[Begin Time]
            ,SUSER_SNAME( [Transaction SID]) AS [User]
            ,[Operation] FROM fn_dblog (NULL, NULL) WHERE [Transaction Name] = 'TRUNCATE TABLE'),
    
    ObjectCte AS
                          (SELECT
                                [Lock Information]
                                ,[Transaction Name]
                                ,[Transaction Id]
                          FROM fn_dblog (NULL, NULL)
                          WHERE [Transaction Id] IN (SELECT
                                                                                       [Transaction Id]
                                                                          FROM       fn_dblog(NULL, NULL)
                                                                          WHERE       [Transaction Name] = 'TRUNCATE TABLE' )
                                       AND [Lock Information] LIKE '%SCH_M OBJECT%'),
    
    ConvertStringToRows ( [Lock Information], starts, pos, [Transaction ID]) AS
                          (SELECT
                                [Lock Information]
                                ,1
                                ,CHARINDEX( ':', [Lock Information])
                                ,[Transaction ID]
                          FROM ObjectCte UNION ALL SELECT
                                [Lock Information]
                                ,pos + 1
                                ,CHARINDEX( ':', [Lock Information], pos + 1)
                                ,[Transaction ID]
                          FROM ConvertStringToRows
                          WHERE pos > 0 ),
    
    ConvertStringToRowsDetails AS (SELECT
            *
            ,RowN = ROW_NUMBER () OVER (PARTITION BY [Lock Information] , [Transaction ID] ORDER BY Starts , [Transaction ID] )
            ,ColumnType =
                                       CASE ROW_NUMBER () OVER (PARTITION BY [Lock Information], [Transaction ID] ORDER BY Starts , [Transaction ID] )
                                              WHEN 3 THEN 'Database'
                                              WHEN 4 THEN 'Object'
                                       END
            ,DetailsID = SUBSTRING ([Lock Information], starts, CASE
                   WHEN pos > 0 THEN pos - starts
                   ELSE LEN ([Lock Information])
            END)
    
    FROM ConvertStringToRows )
    
    , CTE_Report
                          AS (SELECT
                                e.*
                                ,ObjectID = ob .DetailsID
                                ,DatabaseID = db .DetailsID
                                ,o. [Lock Information]
                                ,TableName = OBJECT_NAME (ob. DetailsID, db.DetailsID )
                                ,[Database] = DB_NAME (db. DetailsID)
                          FROM TranCte e
                          JOIN ObjectCte o
                                ON e .[Transaction Id] = o .[Transaction Id]
                          JOIN ConvertStringToRowsDetails db
                                ON o .[Lock Information] = db .[Lock Information]
                                AND db .ColumnType = 'Database'
                          JOIN ConvertStringToRowsDetails ob
                                ON o .[Lock Information] = ob .[Lock Information]
                                AND ob .ColumnType = 'Object' )
    
    
    SELECT        * FROM CTE_Report
    

1 个答案:

答案 0 :(得分:1)

该代码将每次引用您当前所在的数据库的系统表,因此仅显示该数据库的数据。

如果要跨数据库执行它,您需要将代码放入每个数据库并使用您已经尝试过的方法之一从那里运行,或者创建复合视图和函数聚合来自指定数据库列表的代码,并从中读取。

或者你可以将所有代码放入动态SQL中,并针对sproc中的指定数据库执行EXEC。但我真的不会这样做。

编辑 - 评论者是对的。忽略我早先的偏见。做动态SQL的事情。它是极少数SO问题之一,它是正确的答案。