rowversion (Transact-SQL)

Tipo di dati che espone i numeri binari univoci generati automaticamente all'interno di un database. rowversion viene in genere utilizzato come meccanismo per la gestione delle versioni delle righe di tabella. Le dimensioni di archiviazione sono di 8 byte. Il tipo di dati rowversion rappresenta un numero incrementale e non mantiene una data o un'ora. Per registrare una data o un'ora, utilizzare il tipo di dati datetime2.

Osservazioni

Ogni database include un contatore che viene incrementato a ogni operazione di inserimento o aggiornamento eseguita su una tabella contenente una colonna di tipo rowversion all'interno del database. Questo contatore è il valore rowversion relativo al database che tiene traccia del tempo relativo all'interno di un database e non del tempo effettivo che può essere associato a un orologio. Ogni tabella può includere una sola colonna di tipo rowversion. A ogni modifica o inserimento di una riga in una colonna di tipo rowversion il valore incrementato rowversion relativo al database viene inserito nella colonna di tipo rowversion. Questa caratteristica rende la colonna rowversion non adatta per le chiavi, in particolare per le chiavi primarie. Gli aggiornamenti eseguiti sulla riga modificano il valore rowversion, con la conseguente modifica del valore della chiave. Se la colonna è una chiave primaria, il valore di chiave precedente non è più valido, come non sono più valide le chiavi esterne che fanno riferimento al valore precedente. Se un cursore dinamico include riferimenti alla tabella, tutti gli aggiornamenti modificano la posizione delle righe all'interno del cursore. Se la colonna è una chiave indice, tutti gli aggiornamenti alle righe di dati comportano l'aggiornamento dell'indice.

timestamp è sinonimo del tipo di dati rowversion ed è conforme alle funzionalità dei sinonimi dei tipi di dati. Nelle istruzioni DDL utilizzare rowversion anziché timestamp, se possibile. Per ulteriori informazioni, vedere Sinonimi dei tipi di dati (Transact-SQL).

Il tipo di dati Transact-SQLtimestamp è diverso dal tipo di dati timestamp definito nello standard ISO.

[!NOTA]

La sintassi timestamp è obsoleta. Questa caratteristica verrà rimossa a partire da una delle prossime versioni di Microsoft SQL Server. Evitare di utilizzare questa funzionalità in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni in cui è attualmente implementata.

In un'istruzione CREATE TABLE o ALTER TABLE non è necessario specificare un nome di colonna per il tipo di dati timestamp, ad esempio:

CREATE TABLE ExampleTable (PriKey int PRIMARY KEY, timestamp);

Se non si specifica un nome di colonna, il Motore di database di SQL Server genera il nome di colonna timestamp. Il sinonimo rowversion non è tuttavia caratterizzato dalla stessa funzionalità. Se si utilizza rowversion, è necessario specificare un nome di colonna, ad esempio:

CREATE TABLE ExampleTable2 (PriKey int PRIMARY KEY, VerCol rowversion) ;

[!NOTA]

Per generare valori rowversion duplicati, utilizzare l'istruzione SELECT INTO nella quale una colonna di tipo rowversion è inclusa nell'elenco SELECT. Non è consigliabile utilizzare rowversion in questo modo.

Una colonna di tipo rowversion che non ammette valori Null equivale dal punto di vista semantico a una colonna di tipo binary(8). Una colonna di tipo rowversion che ammette valori Null equivale dal punto di vista semantico a una colonna di tipo varbinary(8).

È possibile utilizzare la colonna rowversion di una riga per determinare in modo semplice se i valori nella riga sono cambiati dall'ultima lettura. Se la riga è stata modificata, il valore rowversion viene aggiornato. Se invece alla riga non sono state apportate modifiche, il valore rowversion rimane invariato rispetto alla lettura precedente. Per restituire il valore rowversion corrente per un database, utilizzare @@DBTS.

È possibile aggiungere una colonna rowversion a una tabella per consentire la gestione dell'integrità del database quando più utenti eseguono contemporaneamente l'aggiornamento di righe. Potrebbe essere necessario, inoltre, conoscere le righe aggiornate e il relativo numero senza eseguire nuovamente una query nella tabella.

Si supponga ad esempio di avere creato una tabella denominata MyTest e di averla popolata mediante le istruzioni Transact-SQL seguenti.

CREATE TABLE MyTest (myKey int PRIMARY KEY
    ,myValue int, RV rowversion);
GO 
INSERT INTO MyTest (myKey, myValue) VALUES (1, 0);
GO 
INSERT INTO MyTest (myKey, myValue) VALUES (2, 0);
GO

È possibile utilizzare le istruzioni Transact-SQL di esempio seguenti per implementare il controllo della concorrenza ottimistico nella tabella MyTest durante l'aggiornamento.

DECLARE @t TABLE (myKey int);
UPDATE MyTest
SET myValue = 2
    OUTPUT inserted.myKey INTO @t(myKey) 
WHERE myKey = 1 
    AND RV = myValue;
IF (SELECT COUNT(*) FROM @t) = 0
    BEGIN
        RAISERROR ('error changing row with myKey = %d'
            ,16 -- Severity.
            ,1 -- State 
            ,1) -- myKey that was changed 
    END;

myValue è il valore della colonna rowversion relativo alla riga che indica l'ultima volta in cui la riga è stata letta. Tale valore deve essere sostituito dal valore rowversion effettivo. Un esempio del valore rowversion effettivo è 0x00000000000007D3.

È possibile inoltre inserire le istruzioni Transact-SQL di esempio in una transazione. Eseguendo una query sulla variabile @t nell'ambito della transazione, è possibile recuperare la colonna aggiornata myKey della tabella senza rieseguire una query sulla tabella MyTest.

Di seguito viene riportato lo stesso esempio che utilizza la sintassi timestamp.

CREATE TABLE MyTest2 (myKey int PRIMARY KEY
    ,myValue int, TS timestamp);
GO 
INSERT INTO MyTest2 (myKey, myValue) VALUES (1, 0);
GO 
INSERT INTO MyTest2 (myKey, myValue) VALUES (2, 0);
GO
DECLARE @t TABLE (myKey int);
UPDATE MyTest2
SET myValue = 2
    OUTPUT inserted.myKey INTO @t(myKey) 
WHERE myKey = 1 
    AND TS = myValue;
IF (SELECT COUNT(*) FROM @t) = 0
    BEGIN
        RAISERROR ('error changing row with myKey = %d'
            ,16 -- Severity.
            ,1 -- State 
            ,1) -- myKey that was changed 
    END;