简体   繁体   English

SQL RowVersion在触发器中增加数据之前增加

[英]SQL RowVersion incrementing before data has been augmented in Trigger

I've just started using T-SQL's RowVersion and I've noticed something very interesting. 我刚刚开始使用T-SQL的RowVersion,并且发现了一些非常有趣的东西。 I created a Proc to update a table with a RowVersion column and at the end of this proc I print out a humanreadable date representation of RowVersion. 我创建了一个Proc来更新具有RowVersion列的表,并在此过程结束时打印出人可读的RowVersion日期表示。 I also added a Trigger which updates data in the table and prints out RowVersion before and after. 我还添加了一个触发器,该触发器将更新表中的数据并在前后输出RowVersion。 It's given some interesting results... 它给出了一些有趣的结果...

From Insert Proc after data is inserted = 1900-01-01 05:43:13.373 插入数据后从Insert Proc = 1900-01-01 05:43:13.373

From start of Trigger before we change any data = 1900-01-01 05:43:13.377 从触发器开始之前,我们更改任何数据= 1900-01-01 05:43:13.377

From end of trigger after data has changed = 1900-01-01 05:43:13.377 数据更改后从触发结束= 1900-01-01 05:43:13.377

The start of the trigger value for the RowVersion column has changed from the end of the proc value for the RowVersion Column despite the fact we have not augmented any data yet. 尽管我们还没有增加任何数据,但RowVersion列的触发值的起始位置已与RowVersion列的proc值的末尾有所不同。 It's also the same as the end of the Trigger. 它也与触发器的末尾相同。 Why is this? 为什么是这样? Is it something to do with the sequencing of SQL statement execution? 这与SQL语句执行的顺序有关吗? Any help understanding this would be appreciated. 任何帮助理解这一点将不胜感激。 The proc and trigger are listed below: proc和触发器如下所示:

CREATE PROCEDURE [dbo].[TestRowVersionProc]
AS
    INSERT INTO TestRowversion (ID, Number)
    VALUES ('6', '6')

    DECLARE @rv DATETIME 
    SELECT @rv = GenerationNumber FROM TestRowversion WHERE ID = '6'
    SELECT CONVERT(VARCHAR(50), @rv , 121)
GO


CREATE TRIGGER [dbo].[TestRowversion_AfterInsertUpdate] ON [dbo].[TestRowversion] AFTER INSERT,UPDATE
AS
    if @@rowcount = 0 return
    set nocount on

    DECLARE @rv DATETIME 
    SELECT @rv = GenerationNumber FROM TestRowversion WHERE ID = '6'
    SELECT CONVERT(VARCHAR(50), @rv , 121)

    DECLARE @Id NVARCHAR(1) 
    SELECT @Id = ID FROM inserted

    UPDATE TestRowversion
    SET Number = 'FromTrigger'
    WHERE ID = '6'

    SELECT @rv = GenerationNumber FROM TestRowversion WHERE ID = '6'
    SELECT CONVERT(VARCHAR(50), @rv , 121)

GO

https://docs.microsoft.com/en-us/sql/t-sql/data-types/rowversion-transact-sql https://docs.microsoft.com/zh-cn/sql/t-sql/data-types/rowversion-transact-sql

  1. The rowversion data type is just an incrementing number and does not preserve a date or a time. rowversion数据类型只是一个递增数字,并不保留日期或时间。

  2. Each database has a counter that is incremented for each insert or update operation that is performed on a table that contains a rowversion column within the database. 每个数据库都有一个计数器,该计数器针对在数据库中包含rowversion列的表上执行的每个插入或更新操作递增。 This counter is the database rowversion. 此计数器是数据库行版本。 This tracks a relative time within a database, not an actual time that can be associated with a clock. 这将跟踪数据库中的相对时间,而不是可与时钟关联的实际时间。

  3. DATETIME Accuracy Rounded to increments of .000, .003, or .007 seconds DATETIME精度四舍五入为.000,.003或.007秒

The order of execution is, using some actual timestamp values: 执行的顺序是,使用一些实际的时间戳值:

| Event time                | Event time                  | RowVersion |
|---------------------------|-----------------------------|------------|
| Start of trigger          | 2017-12-05 10:50:26.8506034 | 28,804,001 |
|  End  of trigger          | 2017-12-05 10:50:26.8506034 | 28,804,002 |
| After insert              | 2017-12-05 10:50:26.8662212 | 28,804,002 |

You can turn the rowversion into a human readable form with: 您可以使用以下方法将行版本转换为易于阅读的形式:

SELECT CAST(GenerationNumber AS bigint) FROM TestRowVersion --timestamp is an 8-byte (64-bit) integer

Your mental model of the ordering was wrong. 您的订购心理模型是错误的。

Table :

CREATE TABLE TestRowVersion (
    ID varchar(50), 
    Number varchar(50),
    GenerationNumber timestamp
)

Inserting procedure : 插入程序

ALTER PROCEDURE [dbo].[TestRowVersionProc]
AS
    INSERT INTO TestRowversion (ID, Number)
    VALUES ('6', '6')

    DECLARE @rv bigint
    SELECT @rv = CAST(GenerationNumber AS bigint) FROM TestRowversion WHERE ID = '6'
    SELECT CAST(SYSDATETIME() AS varchar(50))+' After insert    '+CAST(@rv AS varchar(50))
GO

Trigger : 触发条件

CREATE TRIGGER [dbo].[TestRowversion_AfterInsertUpdate] ON [dbo].[TestRowversion] AFTER INSERT,UPDATE
AS
    if @@rowcount = 0 return
    set nocount on

    DECLARE @rv bigint
    SELECT @rv = CAST(GenerationNumber AS bigint) FROM TestRowversion WHERE ID = '6'
    SELECT CAST(SYSDATETIME() AS varchar(50))+' Start of trigger    '+CAST(@rv AS varchar(50))

    DECLARE @Id NVARCHAR(1) 
    SELECT @Id = ID FROM inserted

    UPDATE TestRowversion
    SET Number = 'FromTrigger'
    WHERE ID = '6'

    SELECT @rv = CAST(GenerationNumber AS bigint) FROM TestRowversion WHERE ID = '6'
    SELECT CAST(SYSDATETIME() AS varchar(50))+' End of trigger  '+CAST(@rv AS varchar(50))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM