2011-09-30 64 views
37

Tôi có hai cơ sở dữ liệu, có tên là DB1 và ​​DB2 trong Sql server 2008. Hai cơ sở dữ liệu này có cùng bảng và cùng một bảng dữ liệu. Tuy nhiên, tôi muốn kiểm tra xem có bất kỳ sự khác biệt nào giữa dữ liệu trong các bảng này hay không.Làm thế nào để so sánh dữ liệu giữa hai bảng trong cơ sở dữ liệu khác nhau bằng cách sử dụng Sql Server 2008?

Có ai có thể giúp tôi bằng tập lệnh cho việc này không?

+5

Nhận công cụ tốt để thực hiện công việc đó cho bạn! [So sánh SQL Red Gate] (http://www.red-gate.com/products/sql-development/sql-compare/) để so sánh cấu trúc, [So sánh dữ liệu SQL cổng đỏ] (http: // www .red-gate.com/products/sql-development/sql-data-compare /) để so sánh dữ liệu/nội dung của bảng. –

+0

[DB Solo] (http://www.dbsolo.com/) là một công cụ rất hữu ích để so sánh dữ liệu DB cũng như lược đồ. –

Trả lời

5

I'v những điều thực hiện như thế này bằng cách sử dụng Checksum (*) chức năng

Trong essance nó tạo ra một mức độ kiểm tra liên tiếp trên tất cả các dữ liệu cột, sau đó bạn có thể so sánh checksum của mỗi hàng cho mỗi bảng cho mỗi khác, sử dụng một tham gia bên trái, để tìm các hàng khác nhau.

Hy vọng rằng sẽ có ý nghĩa ...

tốt hơn với một ví dụ ....

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

Điều này không hoạt động như 'Tài khoản người dùng' không được xác định. – MoonKnight

+11

Ý của bạn là gì? Mã psuedocode của nó ... – Matt

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

Checksum rằng Matt đề nghị có lẽ là một cách tiếp cận tốt hơn để so sánh cột chứ không phải so sánh mỗi cột

+0

Vì vậy, đối với mỗi bảng chúng ta cần viết truy vấn mới, phải không ??? –

+0

bạn có thể viết một kịch bản lệnh t-sql để tạo tất cả các truy vấn đó theo lập trình. Tất cả siêu dữ liệu nằm trong bảng hệ thống và chế độ xem – evpo

+0

xem câu hỏi này để nhận các khóa chính http://stackoverflow.com/questions/222217/how-do-i-determine-if-a-column-is-in-the-primary -key-of-its-table-sql-server – evpo

2

Nếu cơ sở dữ liệu ở cùng một máy chủ sử dụng định dạng [DatabaseName].[Owner].[TableName] khi truy cập vào bảng nằm trong cơ sở dữ liệu khác.

Ví dụ: [DB1].[dbo].[TableName]

Nếu cơ sở dữ liệu trong cái nhìn máy chủ khác nhau ở trên Creating Linked Servers (SQL Server Database Engine)

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 

mã kiểm tra:

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 

Kết quả:

ID 
----------- 
1 
3 
+0

plz của tôi làm cho tôi hiểu, "ngoại trừ" từ khóa và "công đoàn tất cả" là gì? –

+2

@JagadisSahu "EXCEPT trả về bất kỳ giá trị khác biệt nào từ truy vấn bên trái cũng không được tìm thấy trên truy vấn phù hợp". http://msdn.microsoft.com/en-us/library/ms188055.aspx –

+2

@JagadisSahu "UNION Chỉ định rằng nhiều tập kết quả sẽ được kết hợp và trả về dưới dạng một tập hợp kết quả duy nhất.". http://msdn.microsoft.com/en-us/library/ms180026.aspx –

1

Một giải pháp khác (không T-SQL): bạn có thể sử dụng tiện ích tablediff. Ví dụ, nếu bạn muốn so sánh hai bảng (Localitate) từ hai máy chủ khác nhau (ROBUH01 & ROBUH02), bạn có thể sử dụng lệnh shell này:

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 

Kết quả:

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

tôi thực sự khuyên rằng những người gặp vấn đề này đi và tìm một công cụ so sánh cơ sở dữ liệu của bên thứ ba.

Lý do - những công cụ này tiết kiệm rất nhiều thời gian và làm cho quy trình ít bị lỗi hơn.

Tôi đã sử dụng comparison tools từ ApexSQL (Diff và Diff Diff) nhưng bạn không thể đi sai với các công cụ khác marc_s và Marina Nastenko đã chỉ ra.

Nếu bạn hoàn toàn chắc chắn rằng bạn sẽ chỉ so sánh các bảng một lần thì SQL là tốt nhưng nếu thỉnh thoảng bạn cần điều này, bạn sẽ tốt hơn với một số công cụ của bên thứ ba.

Nếu bạn không có ngân sách để mua thì chỉ cần sử dụng nó ở chế độ dùng thử để hoàn thành công việc.

Tôi hy vọng độc giả mới sẽ tìm thấy điều này hữu ích mặc dù đó là một câu trả lời muộn ...

4

So sánh hai cơ sở dữ liệu trong cơ sở dữ liệu SQL. Hãy thử truy vấn này nó có thể giúp đỡ.

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

Nếu cả hai cơ sở dữ liệu trên cùng một máy chủ. Bạn có thể kiểm tra bảng tương tự bằng cách sử dụng truy vấn sau đây:

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  

Bằng cách liệt kê ra bảng tương tự bạn có thể so sánh các cột schema sử dụng sys.columns xem.

Hy vọng điều này sẽ giúp bạn.

0

Để so sánh hai cơ sở dữ liệu, tôi đã viết các quy trình dưới đây. Nếu bạn muốn so sánh hai bảng, bạn có thể sử dụng thủ tục 'CompareTables'. Ví dụ:

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

Nếu bạn muốn so sánh hai cơ sở dữ liệu, hãy sử dụng thủ tục 'CompareDatabases'. Ví dụ:

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

Lưu ý: - Tôi đã cố gắng thực hiện các quy trình an toàn, tuy nhiên, các quy trình này chỉ dành cho thử nghiệm và gỡ lỗi. - Nếu bạn muốn có giải pháp hoàn chỉnh để sử dụng so sánh bên thứ ba như (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

Điều này khác gì so với câu trả lời được chấp nhận của @Mikael Eriksson? Có vẻ như bạn đã sử dụng lại câu trả lời được chấp nhận và đặt nó trong câu lệnh 'CREATE PROC'. –

Các vấn đề liên quan