私が知っているScope_Identity()
、Identity()
、@@Identity
、およびIdent_Current()
すべてのID列の値を取得するが、私は違いを知っているのが大好きです。
私が持っている論争の一部は、上記のこれらの関数に適用されるスコープによって何を意味するのですか?
また、それらを使用するさまざまなシナリオの簡単な例も気に入りましたか?
私が知っているScope_Identity()
、Identity()
、@@Identity
、およびIdent_Current()
すべてのID列の値を取得するが、私は違いを知っているのが大好きです。
私が持っている論争の一部は、上記のこれらの関数に適用されるスコープによって何を意味するのですか?
また、それらを使用するさまざまなシナリオの簡単な例も気に入りましたか?
回答:
@@identity
関数は、同じセッションで作成された最後のIDを返します。scope_identity()
関数は、同じセッションおよび同じスコープで作成された最後のIDを返します。ident_current(name)
任意のセッションで特定のテーブルやビューのために作成された最後のIDを返します。identity()
関数はIDの取得には使用されませんselect...into
。クエリでIDを作成するために使用されます。セッションはデータベース接続です。スコープは、現在のクエリまたは現在のストアドプロシージャです。
scope_identity()
と@@identity
関数が異なる状況は、テーブルにトリガーがある場合です。レコードを挿入するクエリがあり、トリガーによって別のレコードが挿入される場合、scope_identity()
関数はクエリ@@identity
によって作成されたIDを返し、関数はトリガーによって作成されたIDを返します。
したがって、通常はscope_identity()
関数を使用します。
良い質問。
@@IDENTITY
:SQL接続(SPID)で生成された最後のID値を返します。ほとんどの場合、それは必要なことですが、そうでない場合もあります(トリガーに応答してトリガーが起動されINSERT
、トリガーが別のINSERT
ステートメントを実行する場合など)。
SCOPE_IDENTITY()
:現在のスコープで生成された最後のID値(つまり、ストアドプロシージャ、トリガー、関数など)を返します。
IDENT_CURRENT()
:特定のテーブルの最後のID値を返します。これを使用してからID値を取得しないでください。INSERT
競合状態(つまり、同じテーブルに行を挿入する複数の接続)の影響を受けます。
IDENTITY()
:テーブルの列をID列として宣言するときに使用されます。
詳細については、http : //msdn.microsoft.com/en-us/library/ms187342.aspxを参照してください。
要約すると、行を挿入していて、挿入した行のID列の値を知りたい場合は、常にを使用しますSCOPE_IDENTITY()
。
スコープとセッションの違いを理解していれば、これらの方法を理解するのは非常に簡単です。
Adam Andersonによる非常に素晴らしいブログ投稿がこの違いを説明しています:
セッションとは、コマンドを実行している現在の接続を意味します。
スコープとは、コマンドの直接のコンテキストを意味します。すべてのストアドプロシージャの呼び出しは独自のスコープで実行され、ネストされた呼び出しは呼び出し元のプロシージャのスコープ内のネストされたスコープで実行されます。同様に、アプリケーションまたはSSMSから実行されるSQLコマンドは独自のスコープで実行され、そのコマンドがトリガーを起動すると、各トリガーは独自のネストされたスコープ内で実行されます。
したがって、3つのID検索方法の違いは次のとおりです。
@@identity
このセッションで生成された最後のID値を返しますが、任意のスコープです。
scope_identity()
このセッションおよびこのスコープで生成された最後のID値を返します。
ident_current()
特定のテーブルに対して生成された最後のID値を返し、任意のセッションおよび任意のスコープ。
スコープとは、のグローバルスコープではなく、INSERT
ステートメントを実行するコードコンテキストを意味します。SCOPE_IDENTITY()
@@IDENTITY
CREATE TABLE Foo(
ID INT IDENTITY(1,1),
Dummy VARCHAR(100)
)
CREATE TABLE FooLog(
ID INT IDENTITY(2,2),
LogText VARCHAR(100)
)
go
CREATE TRIGGER InsertFoo ON Foo AFTER INSERT AS
BEGIN
INSERT INTO FooLog (LogText) VALUES ('inserted Foo')
INSERT INTO FooLog (LogText) SELECT Dummy FROM inserted
END
INSERT INTO Foo (Dummy) VALUES ('x')
SELECT SCOPE_IDENTITY(), @@IDENTITY
異なる結果が得られます。
@David Freitasによって言及されたバグのため、および2012年に導入された新しいシーケンス機能への非互換性のため、これら3つすべてを回避することをお勧めします。代わりに、OUTPUT句を使用して、挿入されたID値を取得できます。他の利点は、複数の行を挿入した場合でもOUTPUTが機能することです。
詳細と例については、こちらをご覧ください:アイデンティティの危機
SCOPE_IDENTITYと@@ IDENTITYの違いについて、次の3つのステートメントを含むストアドプロシージャP1があるとします。-
新しいID値を生成するINSERT- 新しい
INSERTステートメントを含むストアドプロシージャP2への呼び出しID値
-関数SCOPE_IDENTITYおよび@@ IDENTITYを照会するステートメントSCOPE_IDENTITY関数は、P1によって生成された値(同じセッションとスコープ)を返します。@@ IDENTITY関数は、P2によって生成された値を返します(スコープに関係なく同じセッション)。