SQL Server RowVersion / Timestamp - Сравнения - PullRequest
26 голосов
/ 17 декабря 2010

Я знаю, что само значение для столбца RowVersion само по себе не полезно, за исключением того, что оно изменяется каждый раз, когда обновляется строка.Тем не менее, мне было интересно, если они полезны для относительного (неравенство) сравнения.

Если у меня есть таблица со столбцом RowVersion, либо одно из следующих истинных:

  • Будут ли все обновления, которые происходят одновременно (либо одна и та же инструкция обновления, либо одна и та же транзакция), иметь одинаковое значение в столбце RowVersion?
  • Если я обновлю «A», а затем «B», будут ли строкиучаствующие в обновлении "B" имеют более высокое значение, чем строки, участвующие в обновлении "A"?

Спасибо.

Ответы [ 8 ]

34 голосов
/ 17 декабря 2010

От MSDN :

У каждой базы данных есть счетчик, который увеличивается на для каждой операции вставки или обновления , выполняемой над таблицейкоторый содержит столбец rowversion в базе данных.Этот счетчик базы данных rowversion.Это отслеживает относительное время в базе данных, а не фактическое время, которое может быть связано с часами. Каждый раз, когда это строка со столбцом rowversion изменяется или вставляется , значение увеличивается база данных rowversion вставляется в столбец rowversion.

http://msdn.microsoft.com/en-us/library/ms182776.aspx

  • Насколько я понимаю, в действительности ничего не происходит одновременно в системе.Это означает, что все rowversion должны быть уникальными.Рискну сказать, что они будут бесполезны, если дубликаты будут разрешены в одной таблице.Также признание того, что rowversion не дублируется, - это позиция MSDN о том, что они не должны использоваться в качестве первичных ключей не потому, что это может привести к нарушениям, а потому, что это вызовет проблемы с внешним ключом.
  • Согласно MSDN, "перевод строкитип данных - просто инкрементное число ... "так что да, позже больше.

На вопрос , насколько он увеличивается, MSDN заявляет," [rowversion] отслеживает относительное время в базе данных ", которое указывает, что оно не является целочисленным приращением, а основано на времени.Однако, это «время» ничего не показывает о том, когда точно , а когда относительно других строк строка была вставлена ​​/ изменена.

13 голосов
/ 19 февраля 2011

Некоторая дополнительная информация.RowVersion хорошо конвертируется в bigint, и, таким образом, при отладке можно отобразить более читаемый вывод:

CREATE TABLE [dbo].[T1](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](50) NULL,
    [RowVer] [timestamp] NOT NULL
) 

insert into t1 ([value]) values ('a')
insert into t1 ([value]) values ('b')
insert into t1 ([value]) values ('c')
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1
update t1 set [value] = 'x' where id = 3
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1
update t1 set [value] = 'y' 
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1

Id  Value   RowVer
1   a   2037
2   b   2038
3   c   2039

Id  Value   RowVer
1   a   2037
2   b   2038
3   x   2040

Id  Value   RowVer
1   y   2041
2   y   2042
3   y   2043
6 голосов
/ 18 марта 2014

Я потратил целую вечность, пытаясь что-то с этим уточнить - попросить обновить столбцы после определенного порядкового номера. Отметка времени на самом деле представляет собой просто порядковый номер - она ​​также является бигендовой, когда функции c #, такие как BitConverter.ToInt64, требуют littleendian.

В итоге я создал представление базы данных для таблицы, из которой я хочу получить данные, с псевдонимом столбца 'SequenceNo'

SELECT     ID, CONVERT(bigint, Timestamp) AS SequenceNo
FROM         dbo.[User]

c # Код сначала видит представление (т.е. UserV) идентично обычной таблице

тогда в моем linq я могу присоединиться к представлению и родительской таблице и сравнить с порядковым номером

var users =  (from u in context.GetTable<User>()
                join uv in context.GetTable<UserV>() on u.ID equals uv.ID
                where mysequenceNo < uv.SequenceNo
                orderby uv.SequenceNo
                select u).ToList();

чтобы получить то, что я хочу - все записи изменились с момента последней проверки.

5 голосов
/ 04 июля 2012

Как примечание, timestamp устарела в SQL Server 2008 и выше. rowversion следует использовать вместо.

С этой страницы в MSDN:

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

5 голосов
/ 17 декабря 2010

Что заставляет вас думать, что типы данных Timestamp - это зло?Тип данных очень полезен для проверки параллелизма.Linq-To-SQL использует этот тип данных именно для этой цели.

Ответы на ваши вопросы:

1) Нет. Это значение обновляется при каждом обновлении строки.Если вы обновляете строку, скажем, пять раз, каждое обновление будет увеличивать значение метки времени.Конечно, вы понимаете, что обновления, которые «происходят одновременно», действительно не происходят.Они по-прежнему происходят только по одному, по очереди.

2) Да.

3 голосов
/ 17 декабря 2010

Rowversion нарушает один из «идеалистических» подходов SQL - оператор UPDATE является единичным атомарным действием и действует так, как если бы происходили все UPDATE (как для всех столбцов в строке, так и для всех строк в таблице)"в то же время".Но в этом случае с помощью Rowversion можно определить, что одна строка была обновлена ​​в немного другое время, чем другая.

Обратите внимание, что порядок обновления строк (с помощью одного оператора обновления) не являетсягарантировано - может, по совпадению, следовать тому же порядку, что и кластеризованный ключ для таблицы, но я бы не стал рассчитывать, что это правда.

2 голосов
/ 14 января 2014

Чтобы ответить на часть вашего вопроса: вы можете получить повторяющиеся значения в соответствии с MSDN:

Дублирующие значения строк могут быть сгенерированы с помощью оператора SELECT INTO, в котором столбец обращения строк находится вВЫБЕРИТЕ список.Мы не рекомендуем использовать Rowversion таким способом.

Источник: Rowversion (Transact-SQL)

1 голос
/ 15 апреля 2011

Каждая база данных имеет счетчик, который увеличивается один за другим при каждой модификации данных, которая выполняется в базе данных. Если таблица, содержащая затронутую (путем обновления / вставки) строку, содержит столбец метки времени / строки, текущее значение счетчика базы данных сохраняется в этом столбце обновленной / вставленной записи.

...