Подтвердить что ты не робот

SQL Server RowVersion/Timestamp - Сравнение

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

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

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

Спасибо.

4b9b3361

Ответ 1

Из MSDN:

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

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

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

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

Ответ 2

Дополнительная информация. 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

Ответ 3

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

Я закончил создание представления db в таблице, в которой я хочу данные, с столбцом псевдонима "SequenceNo"

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

С# Код сначала видит вид (т.е. 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();

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

Ответ 4

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

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

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

2) Да.

Ответ 5

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

От эта страница в MSDN:

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

Ответ 6

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

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

Ответ 7

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

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

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

Ответ 8

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