Je sais que la valeur elle-même pour une colonne RowVersion
n'est pas en soi utile, sauf qu'elle change chaque fois que la ligne est mise à jour. Cependant, je me demandais s'ils sont utiles pour la comparaison relative (inégalité).
Si j'ai une table avec une colonne RowVersion
, l'une des valeurs suivantes est-elle vraie:
RowVersion
?Merci.
Chaque base de données possède un compteur incrémenté pour chaque opération d'insertion ou de mise à jour effectuée sur une table contenant une colonne rowversion
dans le base de données. Ce compteur est la base de données rowversion
. Cela permet de suivre une heure relative dans une base de données, pas une heure réelle qui peut être associée à une horloge. Chaque fois que une ligne avec une colonne rowversion
est modifiée ou insérée , la base de données incrémentée rowversion
la valeur est insérée dans la colonne rowversion
.
http://msdn.Microsoft.com/en-us/library/ms182776.aspx
rowversion
doivent être uniques. J'ose dire qu'ils seraient effectivement inutiles si les doublons étaient autorisés dans le même tableau. Donner également crédit aux rowversion
s qui ne sont pas dupliqués est la position de MSDN de ne pas les utiliser comme clés primaires non pas parce que cela provoquerait des violations, mais parce que cela provoquerait des problèmes de clé étrangère.À la question de combien il incrémente, MSDN déclare, "[rowversion
] suit un temps relatif dans une base de données", ce qui indique qu'il ne s'agit pas d'un incrément entier fluide, mais basé sur le temps. Cependant, ce "temps" ne révèle rien quand exactement, mais plutôt quand par rapport aux autres lignes une ligne a été insérée/modifiée.
Quelques informations supplémentaires. RowVersion se convertit bien en bigint et donc on peut afficher une meilleure sortie lisible lors du débogage:
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
J'ai passé des années à essayer de trier quelque chose avec cela - pour demander des colonnes mises à jour après un numéro de séquence particulier. L'horodatage n'est en réalité qu'un numéro de séquence - il est également bigendien lorsque des fonctions c # comme BitConverter.ToInt64 veulent littleendian.
J'ai fini par créer une vue db sur la table dont je veux des données avec une colonne d'alias 'SequenceNo'
SELECT ID, CONVERT(bigint, Timestamp) AS SequenceNo
FROM dbo.[User]
le code c # voit d'abord la vue (c'est-à-dire UserV) de façon identique à une table normale
puis dans mon linq je peux rejoindre la vue et la table parent et comparer avec un numéro de séquence
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();
pour obtenir ce que je veux - toutes les entrées ont changé depuis la dernière fois que j'ai vérifié.
Qu'est-ce qui vous fait penser que les types de données d'horodatage sont mauvais? Le type de données est très utile pour la vérification des accès concurrents. Linq-To-SQL utilise ce type de données à cet effet.
Les réponses à vos questions:
1) Non. Cette valeur est mise à jour à chaque mise à jour de la ligne. Si vous mettez à jour la ligne cinq fois, chaque mise à jour incrémentera la valeur d'horodatage. Bien sûr, vous réalisez que les mises à jour qui "se produisent simultanément" ne le sont vraiment pas. Ils ne se produisent toujours que l'un après l'autre, à leur tour.
2) Oui.
Tout comme une note, timestamp
est déconseillé dans SQL Server 2008. rowversion
doit être utilisé à la place.
De cette page sur MSDN:
La syntaxe d'horodatage est déconseillée. Cette fonctionnalité sera supprimée dans une future version de Microsoft SQL Server. Évitez d'utiliser cette fonctionnalité dans de nouveaux travaux de développement et prévoyez de modifier les applications qui utilisent actuellement cette fonctionnalité.
Rowversion rompt l'une des approches "idéalistes" de SQL: une instruction UPDATE est une action atomique unique et agit comme si toutes les UPDATE (toutes les colonnes d'une ligne et toutes les lignes de la table) se produisaient "à la en même temps". Mais dans ce cas, avec Rowversion, il est possible de déterminer qu'une ligne a été mise à jour à un moment légèrement différent d'une autre.
Notez que l'ordre dans lequel les lignes sont mises à jour (par une seule instruction de mise à jour) n'est pas garanti - il peut, par coïncidence, suivre le même ordre que la clé en cluster de la table, mais je ne compterais pas sur le fait que cela soit vrai.
Pour répondre à une partie de votre question: vous pouvez vous retrouver avec des valeurs en double selon MSDN:
Des valeurs de version de ligne en double peuvent être générées à l'aide de l'instruction SELECT INTO dans laquelle une colonne de version de ligne se trouve dans la liste SELECT. Nous ne recommandons pas d'utiliser rowversion de cette manière.
Source: rowversion (Transact-SQL)
Chaque base de données possède un compteur qui est incrémenté un par un à chaque modification de données effectuée dans la base de données. Si la table contenant la ligne affectée (par mise à jour/insertion) contient une colonne d'horodatage/version de ligne, la valeur actuelle du compteur de la base de données est stockée dans cette colonne de l'enregistrement mis à jour/inséré.