Overblog Folge diesem Blog
Edit post Administration Create my blog
Blog von Olaf Helper

Insert und Update Timestamp für MS Sync Framework

20. Mai 2009 , Geschrieben von Olaf Helper Veröffentlicht in #T-SQL

 

Wer sich schon mal mit dem Microsoft Sync Framework für .NET beschäftigt hat, weiß das man für eine Batch Synchronisation in den Tabellen mindestens zwei Timestamp-Felder benötigt; eins für Insert und eins für Update.

Natürlich kann man in einer Tabelle nicht 2 oder mehr Felder mit Typ Timestamp anlegen; macht ja auch keinen Sinn, da bei jedem Update alle Felder auf das gleiche aktuelle Timestamp gesetzt werden würde.

Im MS SQL Server ist das mit einem einfachen Kniff leicht möglich, ohne eine Programmanpassung vornehmen zu müssen. Für Update legt man ein Feld mit Typ Timestamp an, für Insert ein Feld vom Typ Binary(8), bei dem das Default auf @@DBTS +1 gesetzt wird. Natürlich weist man dem Feld nie ein Wert zu, sondern belässt man den Default; also dem Timestamp zu Zeitpunkt des Inserts.

Sieht dann so aus:

 

 USE tempdb  
 --TempDB um mit @@DBTS die richtigen Werte zu bekommen 
 GO 
 CREATE TABLE #TS 
  (Id int identity(1,1), 
   UpdateTS timestamp, 
   InsertTS binary(6) DEFAULT @@DBTS + 1); 
   
 -- 3 Datensätze zur Demo 
 INSERT INTO #TS DEFAULT VALUES; 
 INSERT INTO #TS DEFAULT VALUES; 
 INSERT INTO #TS DEFAULT VALUES; 
 -- Einen davon Updaten 
 UPDATE #TS 
 SET InsertTS = InsertTS 
 WHERE Id = 3 
 -- Wie sieht es aus? 
 SELECT * FROM #TS; 
 -- ... gut 
 GO 
 DROP TABLE #TS 

 

Ergebnis:

 

 Id UpdateTS InsertTS 
 ----------- ------------------ -------------- 
 1 0x000000000000401C 0x00000000401C 
 2 0x000000000000401D 0x00000000401D 
 3 0x000000000000401F 0x00000000401E 

 

Wie erwartet und gewünscht.

 

Nun möchte ich das Ganze mit einer MS SQL Server Compact Editon 3.5 SP1 Datenbank nutzen.

Wenn man zur Tabellen-Anlage das SQL Server Management Studio nutzt, fällt einen zunächst mal auf, das im SQL Server CE der Datentyp nun RowVersion statt Timestamp heißt; sehr positiv, wie ich finde, den Timestamp ist irreführend, das es nichts mit Datum – Uhrzeit zu tun hat; es ist nur eine fortlaufende Nummer und RowVersion ist die wesentlich passendere Bezeichnung; bleibt zu Hoffen, dass die Bezeichnung dann demnächst auch im SQL Server Einzug hält; vielleicht schon mit SQL Server 2008 R2? Beim CREATE TABLE kann man sowohl Timestamp als auch RowVersion verwenden; ich verwende mal zu Demo-Zwecken letzteres.

 

Hier also das Script für SQL Server CE 3.5; man muss aber jeden Befehl einzeln im SSMS ausführen, da keine Batches unterstütz werden. Das bei @@DBTS das + 1 fehlt, liegt daran, das beim ersten Test ein falscher (um eins zu hoher) Wert raus kam … aber das kommt noch.

 

 -- Bei CE jeden Schritt einzeln abarbeiten!! 
 CREATE TABLE TS 
  (Id int identity(1,1), 
   UpdateTS rowversion, 
   InsertTS binary(8) DEFAULT @@DBTS); 
   
 -- 3mal einzeln ausführen, bitte! 
 INSERT INTO TS (UpdateTS) VALUES(NULL); 
   
 -- Einen davon Updaten 
 UPDATE TS 
 SET InsertTS = InsertTS 
 WHERE Id = 3 
   
 SELECT * FROM TS; 
   
 GO 
 DROP TABLE TS 

 

Ergebnis:

 

 Id UpdateTS InsertTS 
 ----------- ------------------ ------------------ 
 1 0x000000000000003F 0x000000000000003F 
 2 0x0000000000000040 0x000000000000003F 
 3 0x0000000000000042 0x000000000000003F 

 

Ähem, ja; es funktioniert … fast so irgendwie. Es hat den Anschein, dass zum Zeitpunkt der Tabellenanlage die Funktion @@DBTS aufgelöst und danach nur noch dieser Wert verwendet wird, nicht der aktuelle. Das ist natürlich suboptimal. Hilft also alles nichts, man muss sein Insert-Statement anpassen in der Form:

 

INSERT INTO TS (InsertTS) VALUES(@@DBTS + 1);

 

Hier also doch wieder @@DBTS + 1.

Ergebnis:

 

 Id UpdateTS InsertTS 
 ----------- ------------------ ------------------ 
 1 0x000000000000003F 0x000000000000003F 
 2 0x0000000000000040 0x000000000000003F 
 3 0x0000000000000042 0x000000000000003F 
 4 0x0000000000000043 0x0000000000000043 
 5 0x0000000000000044 0x0000000000000044 

 

Was sagt uns das? Immer alles ausgiebig testen, auch wenn es zunächst augenscheinlich funktioniert.

Diesen Post teilen

Repost 0

Kommentiere diesen Post