Cara mengetahui perbedaan konten antara 2 tabel SQL dan menghasilkan sinkronisasi SQL

12

Bagaimana cara mengetahui perbedaan data antara dua tabel yang memiliki skema yang tepat, dan bagaimana menghasilkan sinkronisasi SQL untuk mendapatkan hasil gabungan (tanpa duplikat)?

Ini adalah 2 tabel:

SOURCE01.dbo.Customers (31,022 rows)

TARGET01.dbo.Customers (29,300 rows)

Skema setiap tabel adalah:

  • [CustomerId] : nvarchar(255)
  • [CustomerSerializedProfile]: nvarchar(max)
  • [CreatedDatetime] : DateTime
Dio Phung
sumber

Jawaban:

6

Selain tablediff dan PowerShell yang disebutkan dalam jawaban sebelumnya, Anda juga dapat menggunakan SQL dengan pernyataan UNION ALL untuk menemukan catatan yang tidak cocok dalam 2 tabel identik:

SELECT MIN(TableName) AS TableName
   ,ID
   ,NAME
   ,lastname
   ,Address
   ,City
FROM (
SELECT 'Table A' AS TableName
    ,Customers.id
    ,Customers.NAME
    ,Customers.lastname
    ,Customers.Address
    ,Customers.City
FROM Customers

UNION ALL

SELECT 'Table B' AS TableName
    ,CustomersOld.id
    ,CustomersOld.NAME
    ,CustomersOld.lastname
    ,CustomersOld.Address
    ,CustomersOld.City
FROM CustomersOld
) tmp
GROUP BY ID
   ,NAME
   ,lastname
   ,Address
   ,City
HAVING COUNT(*) = 1
ORDER BY id;

Opsi lain yang bisa Anda coba adalah menggunakan Data Compare di Visual Studio itu sendiri. Ini membandingkan data dalam database sumber dan database target dan membuat skrip sinkronisasi untuk tabel yang Anda pilih untuk sinkronisasi.

Dan yang terakhir, namun tidak kalah pentingnya, Anda dapat menggunakan alat perbandingan data SQL - ApexSQL Data Diff , untuk mengatur semua opsi sinkronisasi, memetakan tabel dan kolom dengan nama yang berbeda, membuat kunci Anda sendiri untuk perbandingan di GUI. Anda dapat menjadwalkannya untuk berjalan tanpa pengawasan dan yang harus Anda lakukan adalah memeriksa riwayat pekerjaan SQL Server di pagi hari. Jika Anda memerlukan detail lebih lanjut mengenai opsi ini, saya sarankan membaca artikel ini: http://solutioncenter.apexsql.com/automatically-compare-and-synchronize-sql-server-data/

Andreas Voller
sumber
4

Menggunakan alat Asli:

tablediff : utilitas tablediff membandingkan data di tabel sumber dengan tabel di tabel tujuan.

PowerShell: Membandingkan objek memungkinkan Anda untuk mencapai itu. ini adalah contoh yang bagus

pihak ketiga:

skema redgate dan perbandingan data. Anda bahkan dapat menggunakan PowerShell dan skema / data dibandingkan untuk mengotomatisasi sesuatu.

Kin Shah
sumber
3

Saya menggunakan ini baru-baru ini untuk tujuan yang sama:

select
    s.*
    ,t.*
from SOURCE01.dbo.Customers as s
full outer join TARGET01.dbo.Customers as t
    on s.CustomerId = t.CustomerId
where s.CustomerSerializedProfile <> t.CustomerSerializedProfile
or s.CreatedDatetime <> t.CreatedDatetime
or s.CustomerId is NULL
or t.CustomerId is NULL;

Itu bergantung pada kunci utama yang konsisten. Tetapi Anda harus memiliki sesuatu yang konsisten. Sebuah skrip meta untuk menghasilkan kode seperti di atas relatif mudah untuk ditulis dan membuat banyak tabel kolom mudah untuk dibandingkan.

Sedangkan untuk sinkronisasi Anda harus source left join targetdan target left join source, kemudian memutuskan apa yang ingin Anda lakukan dengan hasil masing-masing.

Michael Green
sumber
2

Ini akan memberi Anda perbedaan antara dua tabel, Anda kemudian dapat membungkus ini dalam permintaan memasukkan untuk menempatkan perbedaan dari A ke B atau sebaliknya.

SELECT A.CustomerId, A.CustomerSerializedProfile, A.CreatedDatetime
  FROM SOURCE01.dbo.Customers A
 WHERE NOT EXISTS (SELECT B.ID
                 FROM TARGET01.dbo.Customers
                WHERE B.CustomerId= A.CustomerId
                  AND B.CustomerSerializedProfile= A.CustomerSerializedProfile
                  AND B.CreatedDatetime= A.CreatedDatetime)
Reaces
sumber
1

Salah satu alat gratis kami memiliki antarmuka lengkap untuk TableDiff:

http://nobhillsoft.com/Diana.aspx

Juga, periksa alat Perbandingan DB kami. Itu satu-satunya di luar sana yang membandingkan jumlah data yang tidak terbatas (selain yang lain dapat melakukan jutaan dan jutaan rekaman) ... selama Anda membandingkan antara 2 server yang ditautkan

http://nobhillsoft.com/NHDBCompare.aspx

(kami melihat tautan lain di utas ini untuk produk pihak ke-3 jadi kami yakin sah untuk menyebutkan milik kami ... mohon beri tahu kami jika tidak)

Jonathan Scion
sumber
2
AFAIK sah selama jawaban ontopik untuk pertanyaan asli dan Anda menyatakan Anda memiliki koneksi dengan produk. Jadi akan berpikir itu baik-baik saja.
Martin Smith
1

Jika kedua tabel memiliki kunci utama yang mirip, Anda dapat menggunakan strategi di bawah ini untuk membandingkan tabel sumber dan target: (Saya menandai kolom kunci komposit dengan asterik)

with src as (select someCol1*, 
                    someCol2*, 
                    someCol3, 
                    someCol4, 
                    someCol5
             from src_table),

tgt as (select someCol1NameCouldDiffer* as someCol1, 
               someCol2*, 
               someCol3, 
               someCol4, 
               someCol5
        from tgt_table),

--Find which keys have at least 1 non-key column difference:

diffs as (select someCol1, 
                 someCol2 
          from (select all 5 columns 
                from src 
                **union** 
                select all 5 columns 
                from target ) 
           **group by** someCol1, someCol2 
           **having count(*)>1** 

--Reselect all columns you wish to compare from src union target, 
--joining on the keys from "diffs" above to show only records which 
--have data differences.

select * 
from (select all 5 columns 
      from src 
      union 
      select all 5 cols 
       from tgt) t1 
join diffs on t1.someCol1 = diffs.someCol1 
           and t1.someCol2 = diffs.someCol2 
**order by ** someCol1, someCol2 desc

Ini berfungsi karena serikat secara implisit mengembalikan catatan yang berbeda. Jadi untuk setiap baris yang diberikan (diidentifikasi oleh beberapa kunci) di sumber yang Anda harapkan cocok dengan tepat di target, Anda akan mengharapkan penyatuan src dan target untuk mengembalikan 1 baris untuk kunci yang diberikan. Dengan demikian Anda dapat menggunakan strategi di atas untuk mengetahui kunci mana yang mengembalikan hasil gabungan yang memiliki beberapa baris, lalu kueri lagi target serikat src, (kali ini hanya memilih catatan yang memiliki perbedaan dengan bergabung dengan tabel diff) memilih semua kolom yang ingin Anda membandingkan, memesan dengan kolom yang menyusun kunci, dan Anda akan melihat kolom mana yang tidak cocok. Catat nama kolom dalam sumber dan target tidak perlu cocok, karena mereka dapat alias satu sama lain menggunakan pernyataan "sebagai".

mancini0
sumber
0

Untuk menemukan perbedaan antara dua tabel yang identik

SELECT *
FROM SOURCE01.dbo.Customers

UNION

SELECT *
FROM TARGET01.dbo.Customers

KECUALI

SELECT *
FROM SOURCE01.dbo.Customers

INTERSECT

SELECT *
FROM TARGET01.dbo.Customers


Urutan operasi menyebabkan INTERSECT dilakukan terlebih dahulu yang akan memberi Anda dataset hanya baris yang ada di kedua tabel. Kedua, UNION dilakukan yang memberi Anda semua baris dari kedua tabel tanpa duplikat. Akhirnya, KECUALI dilakukan yang menghapus UNION Anda (semua baris dari kedua tabel) dataset INTERSECT yang merupakan baris di kedua tabel. Ini memberi Anda dataset yang hanya berisi baris yang ada di salah satu tabel tetapi tidak di yang lain. Jika dataset Anda kembali kosong maka semua baris adalah sama antara tabel.



https://docs.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql

mihalko
sumber
Hai yang disana! Saya pikir jawaban Anda akan lebih baik jika Anda menggunakan nama tabel dari pertanyaan awal!
Anthony Genovese
0

Saya memiliki masalah yang sama dan menggunakan perintah SQL 'KECUALI' untuk menyelesaikan masalah. Perintah KECUALI mengambil dua pernyataan SELECT dan mengembalikan baris yang dikembalikan oleh pernyataan SELECT pertama (kiri) dan bukan oleh pernyataan SELECT kedua (kanan).

SELECT * from table1 where x,y,z 
EXCEPT
SELECT * from table2 where a,b,c

PS: Skema untuk kedua tabel yang dikembalikan oleh pernyataan SELECT harus cocok.

Untuk lebih jelasnya, kunjungi: Halaman Poin Tutorial di sini

avirup.m97
sumber
0
/*
Compare master table data on 2 servers (
1. Change server name
2. Set RaceDate (@racedate) with the >, < ,= >= operator 
 before you run)

 --KNOWN ISSUES
 1. Tables need PKs

*/
SET NOCOUNT ON

--Destination Server Details
DECLARE @destServ nvarchar(40)='[sql\inst23]'    --required             -- If local instance, leave the string empty 
DECLARE @destdb nvarchar(40)='DBName'         --required        
DECLARE @destSchema nvarchar(40)='dbo'        --required        
DECLARE @destTable  nvarchar(40)='TableName'    --required      

-- Source Server Details
DECLARE @SourServ nvarchar(40)='[sql\inst07]'   --required      
DECLARE @Sourdb nvarchar(40)='DBonRemoteServer'  --required     
DECLARE @SourSchema nvarchar(40)='dbo'          --required      
DECLARE @SourTable  nvarchar(40)='TableName'      --required                                -- TableName format 'MyTable'

DECLARE @WHERE nvarchar(400) = 'WHERE 1=1'

DECLARE @Clause nvarchar(400)= 'AND Id > 201808201500000'       --Choose a Predicate to limit data --Start with AND . e.g: 'AND Date > ''20180801'' '

SELECT @WHERE = @WHERE + @Clause

DECLARE @randomtablesuffix nvarchar(5)
SELECT @randomtablesuffix= SUBSTRING(CAST(NEWID() as nvarchar(255)),1,5)


declare @v nvarchar(max), @sql nvarchar(max), @retval nvarchar(max) , @ParamDef nvarchar(400)

--GET Columns List as varchar Columns for HASHBYTES to compare
SELECT @sql='SELECT @vv= COALESCE(@vv,'''')+''CAST(ISNULL(''+ COLUMN_NAME  + '',0) as VARCHAR(''+ 
        CASE WHEN DATA_TYPE IN (''varchar'',''nvarchar'') THEN CAST(CHARACTER_MAXIMUM_LENGTH as varchar(5)) ELSE ''60 '' END +'')) + ''
from '+ @destdb + '.INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='+ QUOTENAME(@destTable,'''') + ''

SET @ParamDef = N'@vv nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @vv=@v OUTPUT;

SELECT @v= SUBSTRING(@v,0,LEN(@v))

--Keys to JOIN
DECLARE @pkeylistJoinOUT nvarchar(4000)=''
SET @sql='SELECT @pkeylistJoin = ISNULL(@pkeylistJoin,'''') + '' a.''+ QUOTENAME(COLUMN_NAME) + ''=b.''+ QUOTENAME(COLUMN_NAME) + '' AND'' 
    FROM '+@destdb+'.[INFORMATION_SCHEMA].[KEY_COLUMN_USAGE]
    WHERE TABLE_NAME='+ QUOTENAME(@destTable,'''') + ' ORDER BY ORDINAL_POSITION'

SET @ParamDef = N'@pkeylistJoin nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @pkeylistJoin=@pkeylistJoinOUT OUTPUT;  

SELECT @pkeylistJoinOUT = REPLACE(REPLACE(REVERSE( SUBSTRING(REVERSE(@pkeylistJoinOUT), CHARINDEX(']', REVERSE(@pkeylistJoinOUT)), LEN(@pkeylistJoinOUT)) ),']',''),'[','')


--Get Column List 

DECLARE @ColumnListOut nvarchar(max)=''
SET @sql='SELECT  @ColumnList=ISNULL(@ColumnList,'''') + COLUMN_NAME + '',''  FROM '+@destdb +'.[INFORMATION_SCHEMA].[COLUMNS] WHERE TABLE_NAME='+QUOTENAME(@destTable,'''')+ ' ORDER BY ORDINAL_POSITION'

SET @ParamDef = N'@ColumnList nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @ColumnList=@ColumnListOut OUTPUT;  


SET @ColumnListOut=SUBSTRING(@ColumnListOut,0,LEN(@ColumnListOut))

--Now Compare

SELECT @sql='

SELECT a.* INTO ##_destissues'+@randomtablesuffix+' FROM (
SELECT HASHBYTES (''SHA2_512'','+ @v +')HashVal,'+ @ColumnListOut +' FROM '+@destServ+'.'+@destdb+'.'+@destSchema+'.'+@destTable + ' x WITH (NOLOCK) ' + @WHERE + '
)a 
JOIN (
SELECT HASHBYTES (''SHA2_512'','+@v +')HashVal,'+ @ColumnListOut + ' FROM ' +@SourServ +'.'+ @Sourdb+ '.'+@SourSchema+'.'+ @SourTable +' y WITH (NOLOCK)  ' + @WHERE + '
)
b ON '+@pkeylistJoinOUT + ' AND  a.HashVal <> b.HashVal '

--print @sql

exec (@sql)


SELECT @sql='

SELECT b.* INTO ##_sourceissues'+@randomtablesuffix+ ' FROM (
SELECT HASHBYTES (''SHA2_512'','+ @v +')HashVal,'+ @ColumnListOut +' FROM '+@destServ+'.'+@destdb+'.'+@destSchema+'.'+@destTable + ' x WITH (NOLOCK) ' + @WHERE + '
)a 
JOIN (
SELECT HASHBYTES (''SHA2_512'','+@v +')HashVal,'+ @ColumnListOut + ' FROM ' +@SourServ +'.'+ @Sourdb+ '.'+@SourSchema+'.'+ @SourTable +' y WITH (NOLOCK)  ' + @WHERE + '
)
b ON '+@pkeylistJoinOUT + ' AND  a.HashVal <> b.HashVal '


exec (@sql)

--Get Column List for Pivoting
DECLARE @ColumnListOutasVC nvarchar(max)=''

SET @sql='SELECT  @ColumnList=ISNULL(@ColumnList,'''')+  ''CAST(''+ COLUMN_NAME + '' AS VARCHAR(200)) as ''+ COLUMN_NAME + '',''   FROM ' + @destdb+'.[INFORMATION_SCHEMA].[COLUMNS] WHERE TABLE_NAME='+QUOTENAME(@desttable,'''')


SET @ParamDef = N'@ColumnList nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @ColumnList=@ColumnListOutasVC OUTPUT;  

SET @ColumnListOutasVC=SUBSTRING(@ColumnListOutasVC,0,LEN(@ColumnListOutasVC))

--Get PKs as VARCHAR Values

DECLARE @pkeylistJoinOUTVC nvarchar(4000)=''

SET @sql='SELECT @pkeylistJoin = ISNULL(@pkeylistJoin,'''') + ''CAST(''+COLUMN_NAME + '' as varchar(200)) as '' + COLUMN_NAME + ''1,''  FROM '+ @destdb+'.[INFORMATION_SCHEMA].[KEY_COLUMN_USAGE]   WHERE TABLE_NAME='+QUOTENAME(@destTable,'''') + '  ORDER BY ORDINAL_POSITION'

SET @ParamDef = N'@pkeylistJoin nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @pkeylistJoin=@pkeylistJoinOUTVC OUTPUT;    
SET @pkeylistJoinOUTVC=SUBSTRING(@pkeylistJoinOUTVC,0,LEN(@pkeylistJoinOUTVC))
--SELECT @pkeylistJoinOUTVC





SET @sql='
select  * INTO ##_destissuedetail'+@randomtablesuffix+ ' from(
select '+ @pkeylistJoinOUTVC + ', ' + @ColumnListOutasVC
                + '
from 
##_destissues'+ @randomtablesuffix+ '
)c UNPIVOT
(
Vals for ColNames in ('+@ColumnListOut+')
) d'

EXEC( @sql)


SET @sql='
select  * INTO ##_sourceissuedetail'+@randomtablesuffix+' from(
select '+ @pkeylistJoinOUTVC + ', ' + @ColumnListOutasVC
                + '
from 
##_sourceissues'+ @randomtablesuffix+'
)c UNPIVOT
(
Vals for ColNames in ('+@ColumnListOut+')
) d'

EXEC( @sql)

SELECT 'Tables to look for data are ##_destissuedetail'+@randomtablesuffix +' and  ##_sourceissuedetail ' +@randomtablesuffix

SET @sql='
SELECT * FROM ##_destissuedetail'+@randomtablesuffix+ '
EXCEPT
SELECT * FROM ##_sourceissuedetail' +@randomtablesuffix

EXEC (@sql)

Skrip (bila diberikan dengan detail yang relevan) membandingkan 2 tabel (mis. Pelanggan di server1 ke Pelanggan di Server2).

Script ini akan berguna jika Anda membandingkan tabel dengan banyak kolom tetapi berjuang untuk menemukan kolom ketidakcocokan yang tepat.

Saya memiliki tabel dengan 353 kolom dan saya harus membandingkannya dengan tabel lain dan menemukan dengan nilai tidak cocok dan skrip ini akan membantu Anda menemukan tuple yang tepat.

pengguna191127
sumber
-1

Saya pikir Anda harus mencoba xSQL Data Compare , yang akan melakukan trik dalam kasus Anda. Katakanlah misalnya, yang Anda tentukan

SOURCE01.dbo.Customers as the **left table** and
TARGET01.dbo.Customers as the **right table**

Setelah Anda membandingkan tabel, dalam hasil perbandingan, Anda dapat menentukan bahwa Anda hanya ingin menyinkronkan perbedaan dari tabel kiri yang akan menghasilkan skrip SQL untuk dimasukkan ke TARGET01.dbo.Pelanggan semua baris yang tidak ada dalam tabel ini tetapi ada di SOURCE01.dbo.Customers (Mencapai hasil UNION tanpa duplikat). Semoga ini membantu!

Pengungkapan: Saya berafiliasi dengan xSQL.

Endi Zhupani
sumber