SQL Server RowVersion / Временная метка - Сравнения
-
11-10-2019 - |
Вопрос
Я знаю, что само значение для RowVersion
столбец сам по себе не полезен, за исключением того, что он меняется каждый раз, когда обновляется строка.Однако мне было интересно, полезны ли они для относительного сравнения (неравенства).
Если у меня есть таблица с RowVersion
столбец, является ли верным любое из следующих значений:
- Будут ли все обновления, которые происходят одновременно (либо одно и то же заявление об обновлении, либо одна и та же транзакция), иметь одинаковое значение в
RowVersion
колонна? - Если я выполню обновление "A", за которым последует обновление "B", будут ли строки, включенные в обновление "B", иметь более высокое значение, чем строки, включенные в обновление "A"?
Спасибо.
Решение
Каждая база данных имеет счетчик, который увеличение для каждой вставки или обновления операция, которая выполняется на таблице, которая содержит rowversion
столбец в базе данных. Этот счетчик является базой данных rowversion
. Анкет Это отслеживает относительное время в базе данных, а не фактическое время, которое может быть связано с часами. Каждый раз что строка с rowversion
столбец модифицируется или вставлен, увеличен база данных rowversion
ценность вставлен в rowversion
столбец.
http://msdn.microsoft.com/en-us/library/ms182776.aspx
- Насколько я понимаю, на самом деле ничего не происходит одновременно в системе. Это означает, что все
rowversion
S должен быть уникальным. Я рискну сказать, что они были бы эффективно бесполезны, если бы дубликаты были разрешены в одной таблице. Также отдавая должноеrowversion
Не дублируется позиция MSDN в том, что они не используют их в качестве основных ключей не потому, что это вызвало бы нарушения, а потому, что это вызвало бы вопросы внешнего ключа. - Согласно MSDN, «тип данных RowVersion - это просто увеличение числа ...». Так что да, позже он больше.
К вопросу о сколько? он увеличивает, утверждает MSDN, [[[rowversion
] отслеживает относительное время в базе данных, которое указывает на то, что это не целое число жидкости, но основанное на времени. Однако это «время» ничего не показывает, когда в яблочко, но скорее когда по отношению к другим рядам ряд был вставлен/изменен.
Другие советы
Некоторая дополнительная информация. 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
Я потратил целую вечность, пытаясь что-то с этим уладить - запросить столбцы, обновленные после определенного порядкового номера.Временная метка на самом деле является просто порядковым номером - она также является bigendian, когда 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();
чтобы получить то, что я хочу - все записи изменились с момента последней проверки.
Что заставляет вас думать, что типы данных TimeStamp - это зло? Тип данных очень полезен для проверки параллелистики. Linq-to-SQL использует этот тип данных для этой цели.
Ответы на ваши вопросы:
1) Нет. Это значение обновляется каждый раз, когда строка обновляется. Если вы обновляете строку, скажем, пять раз, каждое обновление увеличит значение временной метки. Конечно, вы понимаете, что обновления, которые «происходят одновременно», действительно не делают. Они все еще встречаются только по одному, в свою очередь.
2) Да.
Как примечание, timestamp
устарел в SQL Server 2008 и далее. rowversion
вместо этого следует использовать.
Из эта страница на MSDN:
А временная метка Синтаксис устарел. Эта функция будет удалена в будущей версии Microsoft SQL Server. Избегайте использования этой функции в новой разработке и планируйте изменять приложения, которые в настоящее время используют эту функцию.
Rowversion нарушает один из "идеалистических" подходов SQL - что оператор UPDATE является единым атомарным действием и действует так, как будто все обновления (как для всех столбцов в строке, так и для всех строк в таблице) происходят "одновременно".Но в этом случае, с помощью Rowversion, можно определить, что одна строка была обновлена в несколько иное время, чем другая.
Обратите внимание, что порядок, в котором обновляются строки (с помощью одного оператора update), не гарантируется - по совпадению он может следовать тому же порядку, что и кластеризованный ключ для таблицы, но я бы не стал рассчитывать на то, что это правда.
Чтобы ответить на часть вашего вопроса: вы можете получить дублирующие значения в соответствии с MSDN:
Дублирующие значения RowVersion могут быть сгенерированы с помощью оператора SELECT Into, в котором столбец RowVersion находится в списке SELECT. Мы не рекомендуем использовать Rowversion таким образом.
Источник: RowVersion (Transact-SQL)
Каждая база данных имеет счетчик, который увеличивается на один за другим на каждую модификацию данных, которая проводится в базе данных. Если таблица, содержащая затронутая (обновление/вставка) строка, содержит столбец TimeStamp/RowVersion, текущее значение счетчика базы данных сохраняется в этом столбце обновленной/вставленной записи.