如何使用Sql Server 2008比较不同数据库中两个表之间的数据?

时间:2011-09-30 05:07:53

标签: sql sql-server sql-server-2008

我有两个数据库,在Sql server 2008中名为DB1和DB2。这两个数据库也有相同的表和相同的表数据。但是,我想检查这些表中的数据是否有任何差异。

有人可以帮我一个脚本吗?

9 个答案:

答案 0 :(得分:25)

select * 
from (
      select *
      from DB1.dbo.Table
      except
      select *
      from DB2.dbo.Table
     ) as T
union all
select * 
from (
      select *
      from DB2.dbo.Table
      except
      select *
      from DB1.dbo.Table
     ) as T

测试代码:

declare @T1 table (ID int)
declare @T2 table (ID int)

insert into @T1 values(1),(2)
insert into @T2 values(2),(3)

select * 
from (
      select *
      from @T1
      except
      select *
      from @T2
     ) as T
union all
select * 
from (
      select *
      from @T2
      except
      select *
      from @T1
     ) as T

结果:

ID
-----------
1
3

答案 1 :(得分:24)

我真的建议遇到此问题的人去找第三方数据库比较工具。

原因 - 这些工具可以节省大量时间,并使流程不易出错。

我已经使用了来自ApexSQL的comparison tools(差异和数据差异),但你不能错过marc_s和Marina Nastenko已经指出的其他工具。

如果你完全确定你只是要比较一次表,那么SQL就可以了,但是如果你不时需要这个,那么你最好使用第三方工具。

如果您没有预算购买它,那么只需在试用模式下使用它即可完成工作。

我希望新读者会觉得这很有用,即使这是一个迟到的答案......

答案 2 :(得分:7)

我使用Checksum(*)函数

完成了这样的事情

在essance中,它会在所有列数据上创建行级校验和,然后您可以将每个表的每行的校验和进行比较,使用左连接来查找不同的行。

希望有意义......

更好的例子......

select *
from 
( select checksum(*) as chk, userid as k from UserAccounts) as t1
left join 
( select checksum(*) as chk, userid as k from UserAccounts) as t2 on t1.k = t2.k
where t1.chk <> t2.chk 

答案 3 :(得分:4)

比较SQL数据库中的两个数据库。试试这个查询可能有所帮助。

SELECT T.[name] AS [table_name], AC.[name] AS [column_name],  TY.[name] AS 
   system_data_type FROM    [***Database Name 1***].sys.[tables] AS T  
   INNER JOIN [***Database Name 1***].sys.[all_columns] AC ON T.[object_id] = AC.[object_id]      
   INNER JOIN [***Database Name 1***].sys.[types] TY ON AC.[system_type_id] = TY.[system_type_id] 
   EXCEPT SELECT T.[name] AS [table_name], AC.[name] AS [column_name], TY.[name] AS system_data_type FROM    ***Database Name 2***.sys.[tables] AS T  
   INNER JOIN ***Database Name 2***.sys.[all_columns] AC ON T.[object_id] = AC.[object_id]  
   INNER JOIN ***Database Name 2***.sys.[types] TY ON AC.[system_type_id] = TY.[system_type_id]

答案 4 :(得分:3)

select * from DB1.dbo.Table a inner join DB2.dbo.Table b on b.PrimKey = a.PrimKey 
where a.FirstColumn <> b.FirstColumn ...

Matt推荐的校验和可能是比较列而不是比较每列的更好方法

答案 5 :(得分:2)

如果数据库在同一服务器中,则在访问驻留在不同数据库中的表时使用[DatabaseName].[Owner].[TableName]格式。

例如:[DB1].[dbo].[TableName]

如果不同服务器中的数据库在Creating Linked Servers (SQL Server Database Engine)

上查看

答案 6 :(得分:1)

另一种解决方案(非T-SQL):您可以使用tablediff实用程序。 例如,如果要比较来自两个不同服务器(ROBUH01&amp; ROBUH02)的两个表(Localitate),可以使用此shell命令:

C:\Program Files\Microsoft SQL Server\100\COM>tablediff -sourceserver ROBUH01 -s
ourcedatabase SIM01 -sourceschema dbo -sourcetable Localitate -destinationserver
 ROBUH02 -destinationschema dbo -destinationdatabase SIM02 -destinationtable Lo
calitate

结果:

Microsoft (R) SQL Server Replication Diff Tool Copyright (c) 2008 Microsoft Corporation User-specified agent parameter values: 
-sourceserver ROBUH01 
-sourcedatabase SIM01 
-sourceschema dbo 
-sourcetable Localitate 
-destinationserver ROBUH02 
-destinationschema dbo 
-destinationdatabase SIM02 
-destinationtable Localitate 

Table [SIM01].[dbo].[Localitate] on ROBUH01 and Table [SIM02].[dbo].[Localitate ] on ROBUH02 have 10 differences. 

Err Id Dest. 
Only 21433 Dest. 
Only 21434 Dest. 
Only 21435 Dest. 
Only 21436 Dest. 
Only 21437 Dest. 
Only 21438 Dest. 
Only 21439 Dest. 
Only 21441 Dest. 
Only 21442 Dest. 
Only 21443 
The requested operation took 9,9472657 seconds.
------------------------------------------------------------------------

答案 7 :(得分:0)

如果两个数据库都在同一台服务器上。您可以使用以下查询检查类似的表:

select 
      fdb.name, sdb.name 
from 
      FIRSTDBNAME.sys.tables fdb 
      join SECONDDBNAME.sys.tables sdb
      on fdb.name = sdb.name -- compare same name tables
order by 
      1     

通过列出类似的表格,您可以使用sys.columns视图比较列架构。

希望这会对你有所帮助。

答案 8 :(得分:0)

为了比较两个数据库,我写了下面的程序。 如果要比较两个表,可以使用'CompareTables'过程。示例:

EXEC master.dbo.CompareTables 'DB1', 'dbo', 'table1', 'DB2', 'dbo', 'table2'

如果要比较两个数据库,请使用“CompareDatabases”过程。示例:

EXEC master.dbo.CompareDatabases 'DB1', 'DB2'

注意: - 我试图使程序安全,但无论如何,这些程序仅用于测试和调试。 - 如果您想要一个完整的比较解决方案,请使用第三方(Visual Studio,...)

USE [master]
GO

create proc [dbo].[CompareDatabases]
    @FirstDatabaseName nvarchar(50),
    @SecondDatabaseName nvarchar(50)
    as
begin
    -- Check that databases exist
    if not exists(SELECT name FROM sys.databases WHERE name=@FirstDatabaseName)
        return 0
    if not exists(SELECT name FROM sys.databases WHERE name=@SecondDatabaseName)
        return 0

    declare @result table (TABLE_NAME nvarchar(256))
    SET NOCOUNT ON
    insert into @result EXEC('(Select distinct TABLE_NAME from ' + @FirstDatabaseName  + '.INFORMATION_SCHEMA.COLUMNS '
                                    +'Where TABLE_SCHEMA=''dbo'')'
                            + 'intersect'
                            + '(Select distinct TABLE_NAME from ' + @SecondDatabaseName  + '.INFORMATION_SCHEMA.COLUMNS '
                                    +'Where TABLE_SCHEMA=''dbo'')')

    DECLARE @TABLE_NAME nvarchar(256)
    DECLARE curseur CURSOR FOR
        SELECT TABLE_NAME FROM @result
    OPEN curseur
    FETCH curseur INTO @TABLE_NAME
        WHILE @@FETCH_STATUS = 0
            BEGIN
                print 'TABLE : ' + @TABLE_NAME
                EXEC master.dbo.CompareTables @FirstDatabaseName, 'dbo', @TABLE_NAME, @SecondDatabaseName, 'dbo', @TABLE_NAME
                FETCH curseur INTO @TABLE_NAME
            END
        CLOSE curseur
    DEALLOCATE curseur
    SET NOCOUNT OFF
end
GO

USE [master]
GO

CREATE PROC [dbo].[CompareTables]
    @FirstTABLE_CATALOG nvarchar(256),
    @FirstTABLE_SCHEMA nvarchar(256),
    @FirstTABLE_NAME nvarchar(256),
    @SecondTABLE_CATALOG nvarchar(256),
    @SecondTABLE_SCHEMA nvarchar(256),
    @SecondTABLE_NAME nvarchar(256)
    AS
BEGIN
    -- Verify if first table exist
    DECLARE @table1 nvarchar(256) = @FirstTABLE_CATALOG + '.' + @FirstTABLE_SCHEMA + '.' + @FirstTABLE_NAME
    DECLARE @return_status int
    EXEC @return_status = master.dbo.TableExist @FirstTABLE_CATALOG, @FirstTABLE_SCHEMA, @FirstTABLE_NAME
    IF @return_status = 0
        BEGIN
            PRINT @table1 + ' : Table Not FOUND'
            RETURN 0
        END



    -- Verify if second table exist
    DECLARE @table2 nvarchar(256) = @SecondTABLE_CATALOG + '.' + @SecondTABLE_SCHEMA + '.' + @SecondTABLE_NAME
    EXEC @return_status = master.dbo.TableExist @SecondTABLE_CATALOG, @SecondTABLE_SCHEMA, @SecondTABLE_NAME
    IF @return_status = 0
        BEGIN
            PRINT @table2 + ' : Table Not FOUND'
            RETURN 0
        END

    -- Compare the two tables
    DECLARE @sql AS NVARCHAR(MAX)
    SELECT @sql = '('
                + '(SELECT ''' + @table1 + ''' as _Table, * FROM ' + @FirstTABLE_CATALOG + '.' + @FirstTABLE_SCHEMA + '.' + @FirstTABLE_NAME + ')'
                + 'EXCEPT'
                + '(SELECT ''' + @table1 + ''' as _Table, * FROM ' + @SecondTABLE_CATALOG + '.' + @SecondTABLE_SCHEMA + '.' + @SecondTABLE_NAME + ')'
                + ')'
                + 'UNION'
                + '('
                + '(SELECT ''' + @table2 + ''' as _Table, * FROM ' + @SecondTABLE_CATALOG + '.' + @SecondTABLE_SCHEMA + '.' + @SecondTABLE_NAME + ')'
                + 'EXCEPT'
                + '(SELECT ''' + @table2 + ''' as _Table, * FROM ' + @FirstTABLE_CATALOG + '.' + @FirstTABLE_SCHEMA + '.' + @FirstTABLE_NAME + ')'
                + ')'
    DECLARE @wrapper AS NVARCHAR(MAX) = 'if exists (' + @sql + ')' + char(10) + '    (' + @sql + ')ORDER BY 2'
    Exec(@wrapper)
END
GO

USE [master]
GO

CREATE PROC [dbo].[TableExist]
    @TABLE_CATALOG nvarchar(256),
    @TABLE_SCHEMA nvarchar(256),
    @TABLE_NAME nvarchar(256)
    AS
BEGIN
    IF NOT EXISTS(SELECT name FROM sys.databases WHERE name=@TABLE_CATALOG)
        RETURN 0

    declare @result table (TABLE_SCHEMA nvarchar(256), TABLE_NAME nvarchar(256))
    SET NOCOUNT ON
    insert into @result EXEC('Select TABLE_SCHEMA, TABLE_NAME from ' + @TABLE_CATALOG  + '.INFORMATION_SCHEMA.COLUMNS')
    SET NOCOUNT OFF

    IF EXISTS(SELECT TABLE_SCHEMA, TABLE_NAME FROM @result
                WHERE TABLE_SCHEMA=@TABLE_SCHEMA AND TABLE_NAME=@TABLE_NAME)
        RETURN 1

    RETURN 0
END

GO