2011-09-30 85 views
37

我有兩個數據庫,在Sql server 2008中名爲DB1和DB2。這兩個數據庫也有相同的表和相同的表數據。但是,我想檢查這些表中的數據是否有差異。如何使用Sql Server 2008比較不同數據庫中兩個表之間的數據?

任何人都可以幫我一個腳本嗎?

+5

獲取一個很好的工具來爲你做那份工作! [Red-Gate SQL Compare](http://www.red-gate.com/products/sql-development/sql-compare/)用於結構比較,[Red-Gate SQL Data Compare](http:// www .red-gate.com/products/sql-development/sql-data-compare /)來比較表格的數據/內容。 –

+0

[DB Solo](http://www.dbsolo.com/)是比較DB數據和模式的另一個非常有用的工具。 –

回答

5

心中已經做過這樣的事情在使用它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 
+1

由於沒有定義'UserAccounts',因此不起作用。 – MoonKnight

+11

你是什麼意思?它的僞代碼... – Matt

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

校驗馬特建議可能是一個更好的方法來比較列,而不是比較每一列

+0

因此,對於每個表我們都需要編寫新的查詢,對嗎? –

+0

您可以編寫一個t-sql腳本,以編程方式創建所有這些查詢。所有的元數據在系統表和視圖 – evpo

+0

看到這個問題來獲得主鍵http://stackoverflow.com/questions/222217/how-do-i-determine-if-a-column-is-in-the-primary -key-of-table-sql-server – evpo

23
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 
+0

plz讓我明白,什麼是「except」關鍵字和「union all」? –

+2

@JagadisSahu「EXCEPT返回左查詢中不在正確查詢中找到的任何不同值。」 http://msdn.microsoft.com/en-us/library/ms188055.aspx –

+2

@JagadisSahu「UNION指定多個結果集合並作爲單個結果集返回。」 http://msdn.microsoft.com/en-us/library/ms180026.aspx –

1

另一種解決方案(非T-SQL):您可以使用tablediff實用程序。 例如,如果你想比較兩個不同服務器上的兩個表(Localitate)(ROBUH01 & ROBUH02),你可以用這個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. 
------------------------------------------------------------------------ 
23

我真的建議遇到此問題的人會去找第三方數據庫比較工具。

原因 - 這些工具可以節省很多時間並使過程更少出錯。

我已經使用ApexSQL(差異和數據差異)的comparison tools,但你不能用其他工具marc_s和Marina Nastenko已經指出的錯誤。

如果你確定你只是要比較一次表,那麼SQL很好,但如果你不時需要這個,那麼使用第三方工具會更好。

如果您沒有預算購買它,那麼只需在試用模式下使用它即可完成工作。

我希望新的讀者會發現這個有用的,即使它是一個遲到的回答...

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] 
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視圖列的架構。

希望這可以幫助你。

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 [email protected]) 
     return 0 
    if not exists(SELECT name FROM sys.databases WHERE [email protected]) 
     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 [email protected]_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 [email protected]_SCHEMA AND [email protected]_NAME) 
     RETURN 1 

    RETURN 0 
END 

GO 
+0

這與@Mikael Eriksson接受的答案有何不同?看起來您重用了接受的答案並將其放入「CREATE PROC」語句中。 –

相關問題