Share via


rowversion (Transact-SQL)

データベース内で自動的に生成され、一意の 2 進数を公開するデータ型です。 rowversion は、一般的にはバージョンを記録するテーブル行のメカニズムとして使用されます。 記憶領域のサイズは 8 バイトです。 データ型 rowversion は単に数値を加算していくだけのもので、日付や時刻を保持する機能はありません。 日付や時刻を記録するには datetime2 型を使用します。

説明

各データベースには、データベース内の rowversion 列を含むテーブルで実行される Insert 操作または Update 操作ごとに増加するカウンターがあります。 このカウンターは、データベース rowversion です。 このカウンターは、時計に関連付けられる実際の時刻ではなく、データベース内の相対的な時間を追跡します。 1 つのテーブルに許可される rowversion 列は、1 つだけです。 rowversion 列のある行が変更または挿入されるたびに、増加したデータベース rowversion 値が rowversion 列に挿入されます。 このため、rowversion 列はキー、特に主キーとして適切ではありません。 行を更新すると rowversion 値が変わるので、キーの値も変わります。 列が主キー内にある場合、以前のキーの値は無効になり、この以前の値を参照する外部キーも無効になります。 動的カーソルでテーブルを参照する場合、すべての更新操作はカーソル上の行の位置を変更します。 列がインデックス キー内にある場合、データ行を更新すると、インデックスも更新されます。

timestamp は rowversion データ型のシノニムであり、データ型のシノニムの動作が適用されます。 DDL ステートメントでは、可能な限り timestamp ではなく rowversion を使用してください。 詳細については、「データ型のシノニム (Transact-SQL)」を参照してください。

Transact-SQL timestamp データ型は、ISO 標準で定義されている timestamp データ型とは異なります。

注意

timestamp 構文は推奨されません。 この機能は、将来のバージョンの Microsoft SQL Server では削除される予定です。新しい開発作業では、この機能の使用を避け、現在この機能を使用しているアプリケーションは修正するようにしてください。

CREATE TABLE または ALTER TABLE ステートメントでは、timestamp データ型の列名を指定する必要はありません。次に例を示します。

CREATE TABLE ExampleTable (PriKey int PRIMARY KEY, timestamp);

列名を指定しない場合、SQL Server データベース エンジンは timestamp 列名を生成しますが、rowversion のシノニムの場合は動作が異なります。 rowversion を使用する場合は、列名を指定する必要があります。次に例を示します。

CREATE TABLE ExampleTable2 (PriKey int PRIMARY KEY, VerCol rowversion) ;
注意

rowversion 列が SELECT リスト内にある SELECT INTO ステートメントを使用すると、重複する rowversion 値が生成される場合があります。 このような rowversion は使用しないことをお勧めします。

NULL 値を許容しない rowversion 列は、binary(8) 列と同じ意味です。 NULL 値を許容する rowversion 列は、varbinary(8) 列と同じ意味です。

行の rowversion 列を使用すると、行が前回読み取られて以降、行の値が変更されたかどうかがすぐにわかります。 行が変更された場合、rowversion 値が更新されています。 行が何も変更されていない場合、rowversion 値は前回の読み取り時と同じです。 データベースの現在の rowversion 値を返すには、@@DBTS を使用します。

rowversion 列をテーブルに追加して、複数のユーザーが同時に行を更新しているときに、データベースの整合性を保つことができます。 テーブルに対するクエリを再度実行せずに、行数や更新された行を把握する必要がある場合もあります。

たとえば、MyTest という名前のテーブルを作成するとします。 次の Transact-SQL ステートメントを実行して、テーブルにいくつかのデータを入力します。

CREATE TABLE MyTest (myKey int PRIMARY KEY
    ,myValue int, RV rowversion);
GO 
INSERT INTO MyTest (myKey, myValue) VALUES (1, 0);
GO 
INSERT INTO MyTest (myKey, myValue) VALUES (2, 0);
GO

次に、以下のサンプル Transact-SQL ステートメントを使用して、更新中に MyTest テーブルにオプティミスティック同時実行制御を実装します。

DECLARE @t TABLE (myKey int);
UPDATE MyTest
SET myValue = 2
    OUTPUT inserted.myKey INTO @t(myKey) 
WHERE myKey = 1 
    AND RV = myValue;
IF (SELECT COUNT(*) FROM @t) = 0
    BEGIN
        RAISERROR ('error changing row with myKey = %d'
            ,16 -- Severity.
            ,1 -- State 
            ,1) -- myKey that was changed 
    END;

myValue は、行を前回読み取った時期を示す行の rowversion 列値です。 この値は、実際の rowversion 値で置き換える必要があります。 実際の rowversion 値は、0x00000000000007D3 などになります。

また、サンプル Transact-SQL ステートメントをトランザクションに置くことができます。 トランザクションの範囲内で @t 変数に対してクエリを実行すると、MyTest テーブルに対するクエリを再度実行しなくても、テーブルの更新済みの myKey 列を取得できます。

timestamp 構文を使用した場合の同じ例を次に示します。

CREATE TABLE MyTest2 (myKey int PRIMARY KEY
    ,myValue int, TS timestamp);
GO 
INSERT INTO MyTest2 (myKey, myValue) VALUES (1, 0);
GO 
INSERT INTO MyTest2 (myKey, myValue) VALUES (2, 0);
GO
DECLARE @t TABLE (myKey int);
UPDATE MyTest2
SET myValue = 2
    OUTPUT inserted.myKey INTO @t(myKey) 
WHERE myKey = 1 
    AND TS = myValue;
IF (SELECT COUNT(*) FROM @t) = 0
    BEGIN
        RAISERROR ('error changing row with myKey = %d'
            ,16 -- Severity.
            ,1 -- State 
            ,1) -- myKey that was changed 
    END;

関連項目

参照

ALTER TABLE (Transact-SQL)

CAST および CONVERT (Transact-SQL)

CREATE TABLE (Transact-SQL)

データ型 (Transact-SQL)

DECLARE @local\_variable (Transact-SQL)

DELETE (Transact-SQL)

INSERT (Transact-SQL)

MIN_ACTIVE_ROWVERSION (Transact-SQL)

SET @local\_variable (Transact-SQL)

UPDATE (Transact-SQL)