[PL] Stempel czasowy czy mit ponadczasowy?
W związku z powtarzającymi się pytaniami o to, jak zrzutować dane typu TIMESTAMP na typy daty i czasu i robić inne “cuda, wianki” związane z tym typem (pytania widziałem zarówno na forum WSS.pl, jak i na forum MSDN, jak i na Experts-Exchange.com), postanowiłem napisać tę notkę. A więc po kolei:
- Typ TIMESTAMP zaimplementowany w SQL Server nie ma nic wspólnego z datą i czasem. Został tak nieszczęśliwie nazwany przez programistów MS, ale nie jest to typ daty i czasu ze standardu SQL-92 o tej samej nazwie. A więc, sorry folks, ale rzutowanie TIMESTAMP na DATETIME jest raczej bez sensu (chyba, że chcecie zobaczyć, która wartość jest większa, bo faktycznie ciężko to może być zweryfikować patrząc na binaria) :-)
- Niestety, nazwa pewnej funkcji systemowej – CURRENT_TIMESTAMP – powoduje jeszcze większe zamieszanie. Ta funkcja ma jak najbardziej związek z datą i czasem – zwraca wartość typu DATETIME (CURRENT_TIMESTAMP to synonim dla GETDATE w SQL Server). Tu MS jest zgodny ze standardem SQL-92. Cóż za (nie)konsekwencja, rzekłbym :-)
- Bardziej szczęśliwą nazwą dla typu TIMESTAMP jest ROWVERSION (obu nazw można używać zamiennie). MS twierdzi, że TIMESTAMP ma być "deprecated" i że należy używać właśnie ROWVERSION. Nazwa ROWVERSION lepiej oddaje podstawowe zastosowanie tego typu danych, czyli wersjonowanie wierszy (stara wersja kolumny ROWVERSION może zostać skopiowana do kolumny typu BINARY). Oczywistym zastosowaniem jest też kontrola kolejności, w jakiej rekordy w tabeli lub w całej bazie danych były dodawane lub modyfikowane.
- W SQL Server typ ROWVERSION (odzwyczajajmy się od TIMESTAMP) jest typem binarnym.
CREATE TABLE #temp (
ID int,
Stamp rowversion
)
INSERT #temp (ID) SELECT 1
SELECT Stamp FROM #temp
Wyniki zapytania mogą się różnić, ale będzie to coś na kształt:
Stamp
------------------
0x00000000000007D1
- Kolumny typu ROWVERSION mają służyć do przechowywania informacji o tym, w jakiej kolejności rekordy w konkretnej bazie danych (a w dalszej kolejności – w konkretnej tabeli) były wstawiane/modyfikowane.
- MS gwarantuje unikalność dla wszystkich wartości typu ROWVERSION na poziomie pojedynczej bazy danych.
- Może być tylko jedna kolumna typu ROWVERSION w tabeli.
- Tak, jak do kolumn wyliczanych, nie można wstawiać "rękoma" danych do kolumn typu ROWVERSION (SQL Server sam wstawia odpowiednie wartości).
- Jeśli wstawisz wiersze do tabeli z kolumną typu ROWVERSION, a następnie usuniesz je i wstawisz nowe wiersze, wartości ROWVERSION będą różne (większe) od wartości, jakie były wstawione na usuniętych wierszy.
- Możesz użyć funkcji @@DBTS do zwrócenia wartości, która jako ostatnia została wstawiona do jakiejkolwiek kolumny typu ROWVERSION w bieżącej bazie danych.
I na koniec ciekawostka, a nawet dwie. Można stworzyć kolumnę typu TIMESTAMP (celowo nie ROWVERSION, o czym za chwilę) nie podając jej nazwy:
CREATE TABLE dbo.Test (
ID int,
timestamp
)
Kolumna automatycznie zostanie nazwama [timestamp]. Nie ma możliwości utworzenia tabeli w ten sposób wykorzystując ROWVERSION (może to i dobrze, wolę jawnie nazywać kolumny w tabelach).
I druga ciekawostka – o ile MS twierdzi, że TIMESTAMP jest "deprecated", o tyle jeśli zajrzeć do widoku sys.types na SQL Server 2005 i 2008, typ TIMESTAMP tam jest, a ROWVERSION nie...
A może masz swoje doświadczenia z TIMESTAMP/ROWVERSION i chcesz się nimi podzielić? Śmiało – czekam na komentarze lub maile.