web-dev-qa-db-ja.com

SQL Serverトランザクションの開始時間はどこから取得できますか?

私はSQL Serverのテンポラルテーブルを使用していて、生成された時間はUTC datetime2のトランザクション開始時間です

SQL Serverに同じトランザクションの開始時間を取得するための関数またはテーブルはありますか?最初にシステムバージョン対応テーブルに書き込み、そこから選択する必要のない他の場所で使用できますか?

同じトランザクションの一部である非システムバージョンのテーブルがいくつかあります。SysUTCDateTimeを使用して変化させるのではなく、それらに対して記録されたdatetime2が一致するようにしたいです。

私はsys.dm_tran_active_transactionsからプルしようとしましたが、その日時とローカルサーバーの時間も異なっているようです。

システムのバージョン管理:2017-04-11 14:00:59.4690673

アクティブなトランザクション:2017-04-11 15:00:59.467

4
Trotts

トランザクションの開始時にSELECT SYSUTCDATETIME();の結果を保存する以外に、トランザクションの開始日をdatetime2として確実に取得する方法がわかりません。

ただし、回避策として、次の例のように、テンポラルテーブルの自動生成された行の開始日を返すことができます。

最初に、システムバージョンのテンポラルテーブルを作成します。

IF OBJECT_ID('dbo.TemporalTest', 'U') IS NOT NULL
BEGIN
    ALTER TABLE dbo.TemporalTest SET (SYSTEM_VERSIONING = OFF);
    DROP TABLE dbo.TemporalTest;
END
IF OBJECT_ID('dbo.TemporalTestHistory', 'U') IS NOT NULL
DROP TABLE dbo.TemporalTestHistory;
CREATE TABLE dbo.TemporalTestHistory
(
    TemporalTestID int NOT NULL 
    , RowStartDate datetime2 NOT NULL
    , RowEndDate datetime2 NOT NULL
    , SomeData varchar(100) NOT NULL
) ON [PRIMARY];

CREATE CLUSTERED INDEX CX_TemporarlTestHistory 
ON dbo.TemporalTestHistory(TemporalTestID, RowStartDate, RowEndDate);

CREATE TABLE dbo.TemporalTest
(
    TemporalTestID int NOT NULL IDENTITY(1,1)
        CONSTRAINT PK_TemporalTest
        PRIMARY KEY CLUSTERED
        WITH (DATA_COMPRESSION = PAGE
            , ALLOW_ROW_LOCKS = ON
            , ALLOW_PAGE_LOCKS = ON
            , FILLFACTOR = 100
            , PAD_INDEX = OFF
            )
    , RowStartDate datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL
    , RowEndDate datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL
    , PERIOD FOR SYSTEM_TIME (RowStartDate, RowEndDate)
    , SomeData varchar(100) NOT NULL
) ON [PRIMARY]
WITH (
        SYSTEM_VERSIONING = ON (
            HISTORY_TABLE = dbo.TemporalTestHistory
            , DATA_CONSISTENCY_CHECK = ON
        )
    );

GO

次に、システムバージョン対応テーブルに行を挿入し、その行を変更し、最後に挿入された開始日を表示するトランザクション:

BEGIN TRANSACTION;

DECLARE @t TABLE
(
    RowStartDate datetime2 NOT NULL
);

INSERT INTO dbo.TemporalTest (SomeData)
OUTPUT inserted.RowStartDate
INTO @t (RowStartDate)
VALUES ('Max');

UPDATE dbo.TemporalTest SET SomeData = 'Max2' WHERE TemporalTestID = 1;

SELECT tt.TemporalTestID
    , tt.SomeData
    , tt.RowStartDate
    , tt.RowEndDate
FROM dbo.TemporalTest tt
UNION ALL
SELECT tth.TemporalTestID
    , tth.SomeData
    , tth.RowStartDate
    , tth.RowEndDate
FROM dbo.TemporalTestHistory tth

SELECT TOP(1) StartDate = t.RowStartDate 
FROM @t t;

COMMIT TRANSACTION;

結果:

+ ---------------- + ---------- + --------------------- -------- + ----------------------------- + 
 | TemporalTestID | SomeData | RowStartDate | RowEndDate | 
 + ---------------- + ---------- + -------------- --------------- + ----------------------------- + 
 | 1 | Max2 | 2017-04-11 17:39:29.5290911 | 9999-12-31 23:59:59.9999999 | 
 | 1 |マックス| 2017-04-11 17:39:29.5290911 | 2017-04-11 17:39:29.5290911 | 
 + ---------------- + ---------- + ----- ------------------------ + ------------------------- ---- + 
 
 + ----------------------------- + 
 | StartDate | 
 + ----------------------------- + 
 | 2017-04-11 17:39:29.5290911 | 
 + ----------------------------- + 

テーブル変数@tには、テンポラルテーブルに挿入された各行の行が含まれます。これを使用して、行の開始日を取得します。

2
Max Vernon

私もこれに興味があります。

sys.dm_tran_current_transactionを使用してAFAICTを実行すると、現在のトランザクションのIDを取得できます。

次に、sys.dm_tran_active_transactionsを使用すると、transactions_begin_timeですべてのトランザクションを取得できます

0
jbeeko