簡體   English   中英

SQL RowVersion在觸發器中增加數據之前增加

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

我剛剛開始使用T-SQL的RowVersion,並且發現了一些非常有趣的東西。 我創建了一個Proc來更新具有RowVersion列的表,並在此過程結束時打印出人可讀的RowVersion日期表示。 我還添加了一個觸發器,該觸發器將更新表中的數據並在前后輸出RowVersion。 它給出了一些有趣的結果...

插入數據后從Insert Proc = 1900-01-01 05:43:13.373

從觸發器開始之前,我們更改任何數據= 1900-01-01 05:43:13.377

數據更改后從觸發結束= 1900-01-01 05:43:13.377

盡管我們還沒有增加任何數據,但RowVersion列的觸發值的起始位置已與RowVersion列的proc值的末尾有所不同。 它也與觸發器的末尾相同。 為什么是這樣? 這與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

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

  1. rowversion數據類型只是一個遞增數字,並不保留日期或時間。

  2. 每個數據庫都有一個計數器,該計數器針對在數據庫中包含rowversion列的表上執行的每個插入或更新操作遞增。 此計數器是數據庫行版本。 這將跟蹤數據庫中的相對時間,而不是可與時鍾關聯的實際時間。

  3. DATETIME精度四舍五入為.000,.003或.007秒

執行的順序是,使用一些實際的時間戳值:

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

您可以使用以下方法將行版本轉換為易於閱讀的形式:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM