如何查找对SQL有新记录影响的表列表?

时间:2019-07-03 14:07:33

标签: sql-server tsql

我正在将数据从一个环境导出到另一个环境。我想选择具有已插入或已修改的新记录集的表的列表。

数据库大约有200张表,并且仅自昨天以来10条表记录受到影响,我只想过滤那些表。其中一些表没有 createdate 表列。难以基于对表的普通选择查询来确定记录差异。

如何查找对SQL有新记录集的表的列表? 并且,如果可能的话,仅使用已识别表中的那些新受影响的记录。

我尝试使用此查询,但是此查询未返回实际表。

select * from sysobjects where id in (
select object_id
FROM sys.dm_db_index_usage_stats
WHERE last_user_update > getdate() - 1 )

1 个答案:

答案 0 :(得分:1)

如果您没有时间戳或标识新更改的记录的内容(例如审核,利用触发器或在这些表上启用了Change Data Capture),那么就无法做到。

但是,阅读您的方案后,是否无法忽略已更改或修改的内容,而只是将那200个表从一个环境导出到另一个环境并在目标位置覆盖它?

如果不是,那么您可能只对比较数据感兴趣,而不是识别新更改的记录以识别哪些表不匹配。您可以使用EXCEPT

请参见下面的示例,该示例将两个具有相同表名和模式的数据库进行比较,并使用EXCEPT快速创建两个SQL数据库,并在while循环中运行它们;将影响到的每个表名插入到临时表中。

DECLARE @Counter AS INT
    ,   @Query AS NVARCHAR(MAX)

IF OBJECT_ID('tempdb..#CompareRecords') IS NOT NULL DROP TABLE #CompareRecords
IF OBJECT_ID('tempdb..#TablesNotMatched') IS NOT NULL DROP TABLE #TablesNotMatched
CREATE TABLE #TablesNotMatched (ObjectName NVARCHAR(200))

SELECT
        ROW_NUMBER() OVER( ORDER BY (SELECT 1)) AS RowNr
    ,   t.TABLE_CATALOG
    ,   t.TABLE_SCHEMA
    ,   t.TABLE_NAME
    ,   Query =     'IF' +  CHAR(13)
                +   '(' + CHAR(13)
                +   '   SELECT' + CHAR(13)
                +   '       COUNT(*) + 1' + CHAR(13)
                +   '   FROM' + CHAR(13)
                +   '   (' + CHAR(13)
                +   '       SELECT ' + QUOTENAME(t.TABLE_NAME, '''''') + ' AS TableName, * FROM ' + QUOTENAME(t.TABLE_CATALOG) + '.' + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME) + CHAR(13)
                +   '       EXCEPT' + CHAR(13)
                +   '       SELECT ' + QUOTENAME(t.TABLE_NAME, '''''') + ' AS TableName, * FROM ' + QUOTENAME(t2.TABLE_CATALOG) + '.' + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME) + CHAR(13)
                +   '   ) AS sq' + CHAR(13)
                +   ') > 1' + CHAR(13)
                +   'SELECT ' + QUOTENAME(QUOTENAME(t.TABLE_CATALOG) + '.' + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME), '''''') + ' AS TableNameRecordsNotMatched'
    INTO #CompareRecords
FROM <UAT_DATABASE>.INFORMATION_SCHEMA.TABLES AS t
LEFT JOIN <PROD_DATABASE>.INFORMATION_SCHEMA.TABLES AS t2 ON    t.TABLE_SCHEMA = t2.TABLE_SCHEMA 
                                                            AND t.TABLE_NAME = t2.TABLE_NAME

WHERE t.TABLE_TYPE = 'BASE TABLE'


SET @Counter = (SELECT MAX(RowNr) FROM #CompareRecords)

WHILE @Counter > 0
    BEGIN
        SET @Query = (SELECT cr.Query FROM #CompareRecords AS cr WHERE cr.RowNr = @Counter)
        INSERT INTO #TablesNotMatched
        EXECUTE sp_executesql @Query
        SET @Counter = @Counter - 1
    END

SELECT
        *
FROM #TablesNotMatched

请注意,使用EXCEPT时,两个表的列数和类型必须完全相同。

我希望这会有所帮助。