Ok.. viele kennen dieses Tool, aber noch mehr kennen es nicht, obwohl es schon seit Jahren Bestandteil des SQL Servers ist.
Tablediff kann sehr schnell und auf einfache Art unterschiedliche Daten zwischen Tabellen erkennen und ein Skript generieren, dass den Abgleich schafft. Download? Braucht man nicht! Tablediff ist ein Tool, das mit dem SQL Server mitgeliefert wird.
“C:ProgramFilesMicrosoft SQL Server100COM”
Die Syntax ist spielend einfach..:
tablediff -sourceserver "SQL2008" –sourceuser MrX –sourcepassword abc
-sourcedatabase "Northwind" -sourceschema sales -sourcetable "Customers"
-destinationserver "SQL2008ROM" -destinationdatabase "Nordwind"
-destinationschema sales -destinationtable "Kunden"
Parameter
Neben den Quell und Zielparametern können auch folgende interessante verwendet werden:
-q schneller Vergleich (nur Zeilenzahl und Schema werden verglichen)
-dt Löschen der Zieltabelle, falls vorhanden
-et Name der Tabelle, die erstellt werden sollte
-f Ausgabe in Textdatei
-bf Anzahl der Statements für ein Skript. Bei Erreichen wird ein neues Skript generiert. Nur in Zusammenhang mit -f
-c Auswertung auf Spalteneben
Der Parameter –f bewirkt dass ein Differenzskript generiert wird, in dem INSERT bzw UPDATE Statements für die Synchronisierung sorgen. Parameter –c erzeugt lediglich eine Spaltengenaue Ausgabe welche Datensätze unterschiedlich sind. Das schöne daran ist, das das Ausgabeskript bei einem update nicht etwa einen ganzen Datensatz inkl alle Spalten updaten würde, sondern tatsächlich nur die jeweiligen unterschiedlichen Spalten geupdatet werden.
Beispiel: Angabe des Parameters –c <vergleich auf Spaltenebene
Src. Only 11030
Src. Only 11031Src. Only 11032
Mismatch 11035 Freight
Mismatch 11054 Freight
Src. Only 11056
Mismatch 11057 Freight
Src. Only 11072
Mismatch 11074 Freight
Mismatch 11077 Freight
Dest. Only 11078
The requested operation took 1,4596335 seconds.
Beispiel: Ausgabe einer Skriptdatei mit Parameter –f (Inhalt der Datei)
SET IDENTITY_INSERT [dbo].[b1] ON
UPDATE [dbo].[b1] SET [Freight]=11.6100 WHERE [OrderID] = 10249INSERT INTO [dbo].[b1] ([CustomerID],[EmployeeID],[Freight],[OrderDate],[OrderID],[RequiredDate],[ShipAddress],[ShipCity],[ShipCountry],[ShipName],[ShippedDate],[ShipPostalCode],[ShipRegion],[ShipVia]) VALUES (N’FRANK‘,4,208.5800,N’1996-07-29 00:00:00.000′,10267,N’1996-08-26 00:00:00.000′,N’Berliner Platz 43′,N’München‘,N’Germany‘,N’Frankenversand‘,N’1996-08-06 00:00:00.000′,N’80805′,N’Null‘,1)
UPDATE [dbo].[b1] SET [Freight]=4.5600 WHERE [OrderID] = 10269
UPDATE [dbo].[b1] SET [Freight]=12.6900 WHERE [OrderID] = 10282
INSERT INTO [dbo].[b1] ([CustomerID],[EmployeeID],[Freight],[OrderDate],[OrderID],[RequiredDate],[ShipAddress],[ShipCity],[ShipCountry],[ShipName],[ShippedDate],[ShipPostalCode],[ShipRegion],[ShipVia]) VALUES (N’QUICK‘,8,229.2400,N’1996-08-21 00:00:00.000′,10286,N’1996-09-18 00:00:00.000′,N’Taucherstraße 10′,N’Cunewalde‘,N’Germany‘,N’QUICK-Stop‘,N’1996-08-30 00:00:00.000′,N’01307′,N’Null‘,3)
UPDATE [dbo].[b1] SET [Freight]=6.2700 WHERE [OrderID] = 10302
INSERT INTO [dbo].[b1] ([CustomerID],[EmployeeID],[Freight],[OrderDate],[OrderID],[RequiredDate],[ShipAddress],[ShipCity],[ShipCountry],[ShipName],[ShippedDate],[ShipPostalCode],[ShipRegion],[ShipVia]) VALUES (N’OLDWO‘,8,257.6200,N’1996-09-13 00:00:00.000′,10305,N’1996-10-11 00:00:00.000′,N’2743 Bering St.‘,N’Anchorage‘,N’USA‘,N’Old World Delicatessen‘,N’1996-10-09 00:00:00.000′,N’99508′,N’AK‘,3)
UPDATE [dbo].[b1] SET [Freight]=7.5600 WHERE [OrderID] = 10306
UPDATE [dbo].[b1] SET [Freight]=4.8800 WHERE [OrderID] = 10323
INSERT INTO [dbo].[b1] ([CustomerID],[EmployeeID],[Freight],[OrderDate],[OrderID],[RequiredDate],[ShipAddress],[ShipCity],[ShipCountry],[ShipName],[ShippedDate],[ShipPostalCode],[ShipRegion],[ShipVia]) VALUES (N’SAVEA‘,9,214.2700,N’1996-10-08 00:00:00.000′,10324,N’1996-11-05 00:00:00.000′,N’187 Suffolk Ln.‘,N’Boise‘,N’USA‘,N’Save-a-lot Markets‘,N’1996-10-10 00:00:00.000′,N’83720′,N’ID‘,1)
UPDATE [dbo].[b1] SET [Freight]=12.7500 WHERE [OrderID] = 10330
UPDATE [dbo].[b1] SET [Freight]=7.4600 WHERE [OrderID] = 10604
DELETE FROM [dbo].[b1] WHERE [OrderID] = 11078
SET IDENTITY_INSERT [dbo].[b1] OFF
Achtung
Auf ein paar Dinge muss man allerdings achten:
- Die zu vergleichenden Tabellen müssen ID Werte besitzen.
- Datumsformate machen gerne Schwierigkeiten. So auch hier, wenn man auf versch. Landeseinstellungen trifft. Das läßt sich jedoch sehr leicht lösen, indem man zu Begin des Scripts das zu erwartende Datumsformat setzt mittels SET DATEFORMAT YMD
Anderer Fall: Es wird gar kein Datum übergeben. Ein N’NULL im Skript bedeutet allerdings string, was wiederum kein Datum ist. Folglich muss das Skript an diesen Stellen geändert werden und statt des N’NULL nur ein NULL gesetzt werden.
Coole Sache !
Hallo Andreas,
vor ein paar Jahren war ich mal auf einer Schulung bei Dir in Baden-Baden.
Nun zur Sache:
habe mit tablediff experimentiert aber leider folgendes Problem:
Die Sourcetabelle generiert ID’s automatisch, ebenso werden auf der Destinationtabelle ID’s generiert die den gleichen Wert haben können.
D. h. es können zukünftig meherere Sourcetabellen mit gleiche ID’s bestehen, die auf die gleiche Zieltabelle abgleichen.
Erkennt jedoch tablediff, dass die ID in der Zieltabelle schon varhanden ist, gibt es keinen Abgleich.
Wie könnte eine Lösung aussehen?
In der Praxis haben wir mehrere Prüfanlagen die autark Daten generieren und diese von Zeit zu Zeit auf einer Zieltabelle zentral abspeichern sollen.
Versuch mal mit Except und Intesect zu arbeiten. Die erkenne Unterschiedliche Zeilen bzw gleiche Zeilen zwischen 2 tabellen. Man muss ein bisschen drum herum basteln.
Oder per TSQL Syntax. Mittlerweile gibst auch schon einen Merge..