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

时间:2017-12-05 11:08:16

标签: sql sql-server tsql rowversion

我刚刚开始使用T-SQL的RowVersion,我注意到了一些非常有趣的东西。我创建了一个Proc以使用RowVersion列更新表,并在此proc的末尾打印出RowVersion的可读日期表示。我还添加了一个Trigger,它更新表中的数据并打印出RowVersion之前和之后。它给出了一些有趣的结果......

插入数据后从插入过程= 1900-01-01 05:43:13.373

从触发开始之前我们更改任何数据= 1900-01-01 05:43:13.377

数据发生变化后触发结束= 1900-01-01 05:43:13.377

RowVersion列的触发器值的开始已从RowVersion列的proc值的末尾更改,尽管我们还没有扩充任何数据。它也与Trigger的结尾相同。为什么是这样?它与SQL语句执行的顺序有关吗?任何帮助理解这一点将不胜感激。 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

2 个答案:

答案 0 :(得分:0)

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

  1. rowversion数据类型只是一个递增的数字,不会保留日期或时间。

  2. 每个数据库都有一个计数器,该计数器针对在数据库中包含rowversion列的表上执行的每个插入或更新操作递增。此计数器是数据库rowversion。这会跟踪数据库中的相对时间,而不是可以与时钟关联的实际时间。

  3. DATETIME准确度舍入为.000,.003或.007秒的增量

答案 1 :(得分:0)

执行顺序是,使用一些实际的时间戳值:

| 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 |

您可以将rowversion转换为人类可读的形式:

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

你订购的心理模型是错误的。

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

插入程序

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

<强>触发

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))