次の方法で共有


@@IDENTITY(Transact-SQL)

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceMicrosoft Fabric の SQL データベース

@@IDENTITY は最後に挿入された恒等元値を返すシステム関数です。

Transact-SQL 構文表記規則

構文

@@IDENTITY  

戻り値の型

numeric(38,0)

解説

INSERTSELECT INTO、または一括コピー ステートメントが完了すると、@@IDENTITYには、ステートメントによって生成された最後の ID 値が格納されます。

  • 文が識別列を持つテーブルに影響しなければ、 @@IDENTITYNULLを返します。
  • 複数の行を挿入して複数の単位元値を生成する場合、 @@IDENTITY は最後に生成された単位元値を返します。
  • 文が1つ以上のトリガーを発生させて識別値を生成する挿入を行う場合、文の直後に @@IDENTITY を呼び出すとトリガーによって生成された最後の識別値が返されます。
  • ID 列を持つテーブルに対する挿入アクションの後にトリガーが起動し、そのトリガーが ID 列を持たない別のテーブルに挿入された場合、 @@IDENTITY は最初の挿入の ID 値を返します。 INSERTまたはSELECT INTOステートメントまたは一括コピーが失敗した場合、またはトランザクションがロールバックされた場合、@@IDENTITY値は前の設定に戻りません。

失敗したステートメントとトランザクションによって、テーブルに対する現在の ID が変更され、ID 列値に差異が生じる可能性があります。 テーブルに値を挿入しようとしたトランザクションがコミットされていない場合でも、ID 値はロールバックされません。 たとえば、IGNORE_DUP_KEY違反が原因でINSERT ステートメントが失敗した場合、テーブルの現在の ID 値は引き続きインクリメントされます。

@@IDENTITYSCOPE_IDENTITYIDENT_CURRENT は、いずれもテーブルの IDENTITY 列に挿入された最後の値を返すため、似た関数です。

  • @@IDENTITY SCOPE_IDENTITY 現在のセッション内の任意のテーブルで生成された最後の識別子値を返します。 ただし、 SCOPE_IDENTITY は現在のスコープ内でのみ値を返します。 @@IDENTITY は特定のスコープに限定されません。

  • IDENT_CURRENT スコープとセッションによって制限されません。指定されたテーブルに制限されます。 IDENT_CURRENT 任意のセッションおよびスコープで特定のテーブルに対して生成された識別値を返します。 詳しくは、「IDENT_CURRENT (Transact-SQL)」をご覧ください。

@@IDENTITY関数のスコープは、それが実行されているローカル サーバー上の現在のセッションです。 この関数をリモート サーバーまたはリンク サーバーに適用することはできません。 別のサーバーで ID 値を取得するには、そのリモート サーバーまたはリンク サーバーでストアド プロシージャを実行し、そのストアド プロシージャ (リモートまたはリンク サーバーのコンテキストで実行) に ID 値を収集し、ローカル サーバー上の呼び出し元の接続に返します。

レプリケーションは、レプリケーション トリガーとストアド プロシージャ内で使用されるため、 @@IDENTITY 値に影響を与える可能性があります。 @@IDENTITY 列がレプリケーションアーティクルの一部である場合、最新のユーザー作成 ID の信頼できるインジケーターではありません。 SCOPE_IDENTITY()の代わりに@@IDENTITY関数の構文を使うこともできます。 詳細については、「 SCOPE_IDENTITY (Transact-SQL)」を参照してください。

Note

呼び出し元のストアド プロシージャまたは Transact-SQL ステートメントは、レプリケーションで使用する入れ子になったトリガーのスコープ内での ID ではなく、そのユーザーのステートメントのスコープ内で使用される最新の ID を返す SCOPE_IDENTITY() 関数を使用するように書き直す必要があります。

A. 最後に挿入された ID 値を取得する

次の例では、ID 列 (LocationID) のあるテーブルに行を挿入し、@@IDENTITY を使用して新しい行で使用する ID 値を表示します。

USE AdventureWorks2022;
GO

--Display the value of LocationID in the last row in the table.
SELECT MAX(LocationID) FROM Production.Location;
GO

INSERT INTO Production.Location (Name, CostRate, Availability, ModifiedDate)
VALUES ('Damaged Goods', 5, 2.5, GETDATE());
GO

SELECT @@IDENTITY AS 'Identity';
GO

--Display the value of LocationID of the newly inserted row.
SELECT MAX(LocationID) FROM Production.Location;
GO

B. @@IDENTITYを使用して親行と子行を挿入する

次の例では、 @@IDENTITY を使用して親行の ID 値をキャプチャし、関連する子行を挿入するときに使用する例を示します。 このパターンは、順序入力テーブルと親子テーブル デザインで一般的です。

-- Create sample tables
CREATE TABLE dbo.Orders (
    OrderID int IDENTITY(1, 1) PRIMARY KEY,
    CustomerName nvarchar(100) NOT NULL,
    OrderDate datetime NOT NULL DEFAULT GETDATE()
);

CREATE TABLE dbo.OrderDetails (
    DetailID int IDENTITY(1, 1) PRIMARY KEY,
    OrderID int NOT NULL REFERENCES dbo.Orders(OrderID),
    ProductName nvarchar(100) NOT NULL,
    Quantity int NOT NULL
);
GO

-- Insert a parent row and capture its identity
INSERT INTO dbo.Orders (CustomerName, OrderDate)
VALUES ('Contoso Ltd', GETDATE());

DECLARE @NewOrderID int = @@IDENTITY;

-- Insert child rows using the captured parent identity
INSERT INTO dbo.OrderDetails (OrderID, ProductName, Quantity)
VALUES (@NewOrderID, 'Widget A', 10);

INSERT INTO dbo.OrderDetails (OrderID, ProductName, Quantity)
VALUES (@NewOrderID, 'Widget B', 5);

-- Verify the results
SELECT o.OrderID, o.CustomerName, d.ProductName, d.Quantity
FROM dbo.Orders o
INNER JOIN dbo.OrderDetails d ON o.OrderID = d.OrderID
WHERE o.OrderID = @NewOrderID;
GO

Note

運用コードでは、このパターンに@@IDENTITYするのではなく、SCOPE_IDENTITY()を使用します。 Orders テーブルでトリガーが起動し、ID 列を持つ別のテーブルに挿入を実行した場合、@@IDENTITYは、Orders ID 値ではなく、トリガーの ID 値を返します。 SCOPE_IDENTITY() は、現在のスコープから ID 値のみを返します。

C. @@IDENTITYとSCOPE_IDENTITYの違いを理解する

次の例は、トリガーが関係する場合に @@IDENTITYSCOPE_IDENTITY() が異なる値を返す方法を示しています。

CREATE TABLE dbo.Products (
    ProductID int IDENTITY(1, 1) PRIMARY KEY,
    ProductName nvarchar(100) NOT NULL
);

CREATE TABLE dbo.ProductAudit (
    AuditID int IDENTITY(1000, 1) PRIMARY KEY,
    ProductID int NOT NULL,
    AuditAction nvarchar(50) NOT NULL,
    AuditDate datetime NOT NULL DEFAULT GETDATE()
);
GO

-- Create a trigger that inserts into ProductAudit
CREATE TRIGGER trg_ProductInsert
ON dbo.Products
AFTER INSERT
AS
BEGIN
    INSERT INTO dbo.ProductAudit (ProductID, AuditAction)
    SELECT ProductID, 'INSERT'
    FROM inserted;
END;
GO

-- Insert a product and compare identity values
INSERT INTO dbo.Products (ProductName) VALUES ('Test Product');

SELECT @@IDENTITY AS [@@IDENTITY],
       SCOPE_IDENTITY() AS [SCOPE_IDENTITY];
GO

この例では、SCOPE_IDENTITY()Products テーブル (現在のスコープ) からProductIDを返し、@@IDENTITYProductAudit テーブル (トリガー スコープ) からAuditIDを返します。 ほとんどのアプリケーション シナリオでは、トリガー アクティビティの影響を受けないため、 SCOPE_IDENTITY() が安全な選択です。