Поделиться через


rowversion (Transact-SQL)

Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure

Тип данных, который представляет собой автоматически сформированные уникальные двоичные числа в базе данных. Тип данных rowversion используется в основном в качестве механизма для отметки версий строк таблицы. Размер при хранении составляет 8 байт. Тип данных rowversion представляет собой увеличивающееся число, которое не сохраняет дату или время. Для записи даты или времени используйте тип данных datetime2.

Замечания

Каждая база данных имеет счетчик, который увеличивается при каждой операции вставки или обновления в таблице, содержащей столбец типа rowversion в базе данных. Этот счетчик типа rowversion используется для работы с базами данных. Происходит отслеживание относительного времени базы данных, а не действительного времени, которое может быть связано с часами. В таблице может быть только один столбец типа rowversion. Каждый раз при изменении или вставке строки, содержащей столбец типа rowversion, увеличенное значение rowversion вставляется в столбец типа rowversion. Из-за этого свойства столбец типа rowversion нежелательно использовать в качестве ключа, особенно первичного. Любое обновление, сделанное в строке, изменяет значение rowversion и значение ключа. Если столбец является первичным ключом, старое значение ключа больше недействительно и внешние ключи, ссылающиеся на старое значение, становятся недействительными. Если на таблицу ссылается динамический курсор, все обновления изменяют положение строк в курсоре. Если столбец является ключом индекса, все обновления в строках данных также приводят к обновлению индекса. Значение rowversion увеличивается при каждом выполнении инструкции обновления, даже если значения в строке не изменяются. (Например, если значение в столбце равно 5 и инструкция обновления задает значение 5, это действие считается обновлением, несмотря на отсутствие изменений и значение rowversion увеличивается.)

Тип данных timestamp является синонимом типа данных rowversion и подчиняется правилам поведения синонимов типов данных. В инструкциях на языке описания данных DDL по возможности используйте rowversion вместо timestamp. Дополнительные сведения см. в статье Синонимы типов данных (Transact-SQL).

Тип данных Transact-SQL timestamp отличается от типа данных timestamp, определенного в стандарте ISO.

Примечание.

Синтаксис timestamp является нерекомендуемым. Эта функция будет удалена в будущей версии SQL Server. Избегайте использования этого компонента в новых разработках и запланируйте изменение существующих приложений, в которых он применяется.

В инструкции CREATE TABLE или ALTER TABLE необязательно указывать имя столбца с типом данных timestamp. Рассмотрим пример.

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

Если имя столбца не указать, ядро СУБД SQL Server создаст имя столбца типа timestamp. Однако синоним rowversion не подчиняется этому правилу. При использовании типа данных rowversion указание имени столбца обязательно.

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

Примечание.

При использовании инструкции SELECT INTO, в которой столбец типа rowversion находится в списке SELECT, могут быть сформированы повторяющиеся значения rowversion. Использовать тип данных rowversion таким образом не рекомендуется.

Столбец типа rowversion, который не может принимать значение NULL, семантически эквивалентен столбцу типа binary(8). Столбец типа rowversion, который может принимать значение NULL, семантически эквивалентен столбцу типа varbinary(8).

С помощью столбца rowversion можно легко определить, выполнялась ли инструкция обновления применительно к строке с момента ее последнего считывания. При выполнении инструкции обновления применительно к строке значение rowversion изменяется. Если для строки не выполнялись инструкции обновления, значение rowversion будет таким же, как и при предыдущем считывании. Чтобы вернуть текущее значение rowversion для базы данных, используйте функцию @@DBTS.

Столбец rowversion можно добавить в таблицу, чтобы обеспечить целостность базы данных в случаях одновременного обновления строк несколькими пользователями. Также может возникнуть необходимость в данных о количестве строк и указании обновленных строк без отправки повторного запроса в таблицу.

Например, допустим, что была создана таблица с именем MyTest. Таблица заполняется данными при выполнении следующих инструкций Transact-SQL.

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  

После этого можно использовать следующие инструкции Transact-SQL для реализации оптимистической блокировки таблицы MyTest во время обновления таблицы. Скрипт использует <myRv> для представления значения rowversion на момент последнего считывания строки. Замените это значение фактическим значением rowversion. Примером фактического значения rowversion является 0x00000000000007D3.

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

Эти примеры инструкций Transact-SQL можно также ввести в транзакцию. При запросе переменной @t в области действия транзакции можно получить обновленный столбец myKey таблицы без отправки повторного запроса в таблицу MyTest.

Ниже приведен тот же пример с использованием синтаксиса timestamp. Замените <myTS> фактическим значением 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 = <myTS>;  
IF (SELECT COUNT(*) FROM @t) = 0  
    BEGIN  
        RAISERROR ('error changing row with myKey = %d'  
            ,16 -- Severity.  
            ,1 -- State   
            ,1) -- myKey that was changed   
    END;  

См. также

Инструкция ALTER TABLE (Transact-SQL)
CAST и CONVERT (Transact-SQL)
CREATE TABLE (Transact-SQL)
Типы данных (Transact-SQL)
DECLARE @local_variable (Transact-SQL)
DELETE (Transact-SQL)
INSERT (Transact-SQL)
MIN_ACTIVE_ROWVERSION (Transact-SQL)
SET @local_variable (Transact-SQL)
UPDATE (Transact-SQL)