查看 SQL Server 2012 上所有数据库的截断表
View Truncated Tables from All Databases on SQL Server 2012
我正在从事一个专注于服务器中 t运行cated tables 的项目。该项目的目标是在审计table中记录所有t运行cated tables。我已经编写了下面的代码,该代码在单个数据库上运行良好;但是,我无法 运行 在所有数据库上自动编码。我试过写:
- 光标
- 在存储过程中使用
Exec ('Use ' + @DatabaseName + ';')
。
- 执行 sp_MSforeachDB 和存储过程。
每次我尝试运行所有数据库的存储过程时,它都会在代码存在的数据库上执行。我怎样才能在所有数据库上执行它。
主要查询:
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
该代码每次都会引用您当前所在数据库的系统表,因此只会显示该数据库的数据。
如果您想跨数据库执行它,您需要将代码放入每个数据库,然后使用您已经尝试过的方法之一从那里 运行 它,或者创建复合视图以及从指定的数据库列表中聚合代码并从中读取的函数。
或者您 可以 将所有代码放入动态 SQL 并针对存储过程中的指定数据库执行它。但是我真的不会那样做。
编辑 - 评论者是对的。忽略我之前的偏见。做动态 SQL 的事情。这是为数不多的 SO 问题之一,它是正确的答案。
我正在从事一个专注于服务器中 t运行cated tables 的项目。该项目的目标是在审计table中记录所有t运行cated tables。我已经编写了下面的代码,该代码在单个数据库上运行良好;但是,我无法 运行 在所有数据库上自动编码。我试过写:
- 光标
- 在存储过程中使用
Exec ('Use ' + @DatabaseName + ';')
。 - 执行 sp_MSforeachDB 和存储过程。
每次我尝试运行所有数据库的存储过程时,它都会在代码存在的数据库上执行。我怎样才能在所有数据库上执行它。
主要查询:
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
该代码每次都会引用您当前所在数据库的系统表,因此只会显示该数据库的数据。
如果您想跨数据库执行它,您需要将代码放入每个数据库,然后使用您已经尝试过的方法之一从那里 运行 它,或者创建复合视图以及从指定的数据库列表中聚合代码并从中读取的函数。
或者您 可以 将所有代码放入动态 SQL 并针对存储过程中的指定数据库执行它。但是我真的不会那样做。
编辑 - 评论者是对的。忽略我之前的偏见。做动态 SQL 的事情。这是为数不多的 SO 问题之一,它是正确的答案。