2 SQL tablosu arasındaki içerik farkları nasıl bulunur ve senkronize SQL nasıl üretilir


13

Tam şemaya sahip iki tablo arasındaki veriler arasındaki farkları nasıl bulabilirim ve birleşim sonuçlarını almak için eşitleme SQL'i nasıl üretebilirim (kopyalar olmadan)?

Bunlar 2 tablodur:

SOURCE01.dbo.Customers (31,022 rows)

TARGET01.dbo.Customers (29,300 rows)

Her tablonun şeması:

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

Yanıtlar:


7

Önceki yanıtlarda belirtilen tablediff ve powershell dışında, 2 özdeş tabloda eşleşmeyen kayıtları bulmak için UNION ALL deyimiyle SQL'i de kullanabilirsiniz:

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;

Deneyebileceğiniz başka bir seçenek de Visual Studio'nun kendisinde Veri Karşılaştırması kullanmaktır. Kaynak veritabanındaki ve hedef veritabanındaki verileri karşılaştırır ve senkronizasyon için seçtiğiniz tablolar için bir senkronizasyon komut dosyası oluşturur.

Ve son olarak, ama en önemlisi, tüm senkronizasyon seçeneklerini ayarlamak, farklı adlarla tabloları ve sütunları eşleştirmek, GUI'de karşılaştırma için kendi anahtarlarınızı oluşturmak için SQL veri karşılaştırma aracını - ApexSQL Data Diff'i kullanabilirsiniz. Katılımsız çalışacak şekilde zamanlayabilirsiniz ve tek yapmanız gereken sabah SQL Server iş geçmişini kontrol etmektir. Bu seçeneklerle ilgili daha fazla ayrıntıya ihtiyacınız varsa, bu makaleyi okumanızı öneririz: http://solutioncenter.apexsql.com/automatically-compare-and-synchronize-sql-server-data/



4

Yerel araçları kullanma:

tablediff : tablediff yardımcı programı , kaynak tablodaki verileri hedef tablodaki tabloyla karşılaştırır.

powershell: karşılaştırma nesnesi bunu başarmanızı sağlar. işte iyi bir örnek

üçüncü parti:

redgate şeması ve verileri karşılaştırın. Bir şeyleri otomatikleştirmek için powershell ve şema / veri karşılaştırmasını bile kullanabilirsiniz.


3

Bunu son zamanlarda benzer bir amaç için kullandım:

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;

Birincil anahtarın tutarlı olmasına güvenir. Ama sonuçta tutarlı bir şeye sahip olmalısınız. Yukarıdaki gibi kod oluşturmak için bir meta komut dosyasının yazılması nispeten kolaydır ve çok sütunlu tabloların karşılaştırılmasını kolaylaştırır.

Senkronizasyona gelince source left join targetve target left join sourcesonra her birinin sonucuyla ne yapmak istediğinize karar vermelisiniz.


2

Bu iki tablo arasındaki farkları vermelidir, daha sonra A'dan B'ye farklılıkları koymak için bunu bir ekleme sorgusuna sarabilirsiniz.

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)

1

Ücretsiz araçlarımızdan birinin TableDiff için tam bir arayüzü var:

http://nobhillsoft.com/Diana.aspx

Ayrıca, DB Karşılaştırma aracımızı inceleyin. Sınırsız miktarda veri karşılaştıran tek kişi (diğerlerinin milyonlarca ve milyonlarca kayıt yapamayacağı)… bağlı 2 sunucu arasında karşılaştırma yaptığınız sürece

http://nobhillsoft.com/NHDBCompare.aspx

(biz üçüncü parti ürünler için bu konu diğer bağlantıları gördük bu yüzden bizimkinden söz onun yasal inanıyoruz ... pls değilse bize bildirin)


2
AFAIK, gerçek bir soruya ontopik bir cevap olduğu sürece yasaldır ve ürünle bir bağlantınız olduğunu belirtirsiniz. Bu yüzden iyi olduğunu düşünürdüm.
Martin Smith

1

Her iki tablonun da benzer birincil anahtarları varsa, kaynak ve hedef tabloları karşılaştırmak için aşağıdaki stratejiyi kullanabilirsiniz: (Bileşik anahtar sütunları yıldız ile işaretledim)

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

Sendika dolaylı olarak farklı kayıtları döndürdüğü için bu çalışır. Bu nedenle, kaynaktaki belirli bir satırda (bazı anahtarlarla tanımlanır) tam olarak hedefte eşleşmesini beklersiniz, src ve hedef birliğinin belirli bir anahtar için 1 satır döndürmesini beklersiniz. Böylece, hangi anahtarların birden çok satıra sahip bir birleşim sonucunu döndürdüğünü bulmak için yukarıdaki stratejiyi kullanabilirsiniz , daha sonra src birleşim hedefini tekrar sorgulayın (bu sefer yalnızca fark tablosuyla birleşerek kayıtları olan kayıtları seçerek) istediğiniz tüm sütunları seçin karşılaştırın, anahtarı oluşturan sütunlara göre sıralayın ve tam olarak hangi sütunların eşleşmediğini göreceksiniz. Kaynak ve hedefte bulunan sütun adlarının eşleşmesi gerekmediğini unutmayın, çünkü bunlar bir "as" ifadesi kullanılarak birbirleriyle diğer ad olarak adlandırılabilir.


0

İki özdeş tablolar arasındaki farklar bulmak için

* SEÇ
SOURCE01.dbo.Customers GELEN

BİRLİĞİ

* SELECT'te
TARGET01.dbo.Customers GELEN

HARİÇ

SELECT'in *
SOURCE01.dbo.Customers GELEN

INTERSECT

* SELECT'te
TARGET01.dbo.Customers GELEN


İşlemlerin sırası, ilk önce INTERSECT işlevinin gerçekleştirilmesine neden olur ve bu da size her iki tabloda da bulunan satırların bir veri kümesini verecektir. İkincisi, her iki tablodaki tüm satırları kopya olmadan size veren UNION gerçekleştirilir. Son olarak, BİRLİĞİNİZDEN (her iki tablonun tüm satırları) her iki tablodaki satır olan INTERSECT veri kümesini silen EXCEPT gerçekleştirilir. Bu, yalnızca tablolardan birinde var olan ancak diğerinde bulunmayan satırları içeren bir veri kümesi bırakır. Veri kümeniz boşsa, tüm satırlar tablolar arasında aynıdır.



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


Selam! Orijinal sorudaki tablo adlarını kullandıysanız cevabınızın daha iyi olacağını düşünüyorum!
Anthony Genovese

0

Benzer bir sorun yaşadım ve sorunu çözmek için SQL 'EXCEPT' komutunu kullandım. EXCEPT komutu iki SELECT ifadesi alır ve ikinci (sağ) SELECT ifadesiyle değil, ilk SELECT ifadesiyle (solda) döndürülen satırları döndürür.

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

Not: SELECT deyimi tarafından döndürülen her iki tablonun şeması eşleşmelidir.

Daha fazla netlik için şu adresi ziyaret edin: Tutorials Point Page here


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)

Komut dosyası (ilgili ayrıntılar sağlandığında) 2 tabloyu karşılaştırır (sunucu1'deki Müşteriler ile Sunucu2'deki Müşteriler deyin).

Bir tabloyu birçok sütunla karşılaştırırsanız, ancak tam olarak eşleşmeyen sütunu bulmakta zorlanırsanız, bu komut dosyası kullanışlı olacaktır.

353 Sütunlu bir tablo var ve ben başka bir tabloya karşılaştırmak ve değerleri eşleşen değildi bulmak zorunda kaldı ve bu komut dosyası tam demet bulmanıza yardımcı olacaktır.


-1

Ben senin durumda hile yapacak xSQL Data Compare denemek gerektiğini düşünüyorum . Diyelim ki, belirttiğiniz

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

Eğer tabloları karşılaştırmak sonra karşılaştırma sonucunda, size TARGET01.dbo.Customers içine tüm satırları eklemek için SQL komut dosyası üretecektir sol tablodan sadece farklılıkları eşitlemek istediğinizi belirtebilirsiniz olmayan bu tabloda ancak exist SOURCE01.dbo.Customers içinde (yinelenmemiş UNION sonuç almak). Bu yardımcı olur umarım!

Açıklama: xSQL'e bağlıyım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.