web-dev-qa-db-ja.com

Scope_Identity()、Identity()、@@ Identity、およびIdent_Current()の違いは何ですか?

Scope_Identity()Identity()@@Identity、およびIdent_Current()はすべてID列の値を取得することを知っていますが、違いを知りたいです。

私が抱えている論争の一部は、上記のこれらの機能に適用されるスコープによって何を意味するのでしょうか?

また、それらを使用するさまざまなシナリオの簡単な例が好きですか?

167
Tebo
  • @@identity関数は、同じセッションで作成された最後のIDを返します。
  • scope_identity()関数は、同じセッションおよび同じスコープで作成された最後のIDを返します。
  • ident_current(name)は、セッションの特定のテーブルまたはビューに対して作成された最後のIDを返します。
  • identity()関数はIDの取得には使用されず、select...intoクエリでIDを作成するために使用されます。

セッションはデータベース接続です。スコープは、現在のクエリまたは現在のストアドプロシージャです。

scope_identity()関数と@@identity関数が異なる状況は、テーブルにトリガーがある場合です。レコードを挿入するクエリがあり、トリガーがどこかに別のレコードを挿入する場合、scope_identity()関数はクエリによって作成されたIDを返し、@@identity関数は引き金。

したがって、通常はscope_identity()関数を使用します。

337
Guffa

良い質問。

  • @@IDENTITY:SQL接続で生成された最後のID値(SPID)を返します。ほとんどの場合、必要なものになりますが、そうではない場合があります(INSERTに応答してトリガーが起動され、トリガーが別のINSERTステートメントを実行する場合など)。

  • SCOPE_IDENTITY():現在のスコープ(つまり、ストアドプロシージャ、トリガー、関数など)で生成された最後のID値を返します。

  • IDENT_CURRENT():特定のテーブルの最後のID値を返します。 INSERTからID値を取得するためにこれを使用しないでください。競合状態(つまり、同じテーブルに行を挿入する複数の接続)の影響を受けます。

  • IDENTITY():テーブル内の列をID列として宣言するときに使用されます。

詳細については、 http://msdn.Microsoft.com/en-us/library/ms187342.aspx を参照してください。

要約すると、行を挿入していて、挿入したばかりの行youのID列の値を知りたい場合は、常にSCOPE_IDENTITY()

40
Brannon

スコープとセッションの違いを理解すれば、これらのメソッドを理解するのは非常に簡単になります。

非常に素晴らしい ブログ投稿 Adam Andersonがこの違いを説明しています:

Sessionは、コマンドを実行している現在の接続を意味します。

Scopeは、コマンドの即時コンテキストを意味します。すべてのストアドプロシージャ呼び出しは独自のスコープで実行され、ネストされた呼び出しは呼び出し元プロシージャのスコープ内のネストされたスコープで実行されます。同様に、アプリケーションまたはSSMSから実行されるSQLコマンドは独自のスコープで実行され、そのコマンドがトリガーを起動すると、各トリガーは独自のネストされたスコープ内で実行されます。

したがって、3つのID取得方法の違いは次のとおりです。

@@identityは、thisセッションで生成された最後のID値を返しますが、anyスコープ。

scope_identity()は、thisセッションおよびthisスコープで生成された最後のID値を返します。

ident_current()は、anyセッションおよびanyスコープ内の特定のテーブルに対して生成された最後のID値を返します。

14
Hemant Sakta

スコープとは、@@IDENTITYのグローバルスコープではなく、INSERTステートメントSCOPE_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 

異なる結果が得られます。

12
devio

@David Freitasが言及したバグと、2012年に導入された新しいシーケンス機能との非互換性のため、これら3つすべてから離れることをお勧めします。代わりに、OUTPUT句を使用して、挿入されたID値を取得できます。もう1つの利点は、複数の行を挿入した場合でもOUTPUTが機能することです。

詳細と例については、こちらをご覧ください: Identity Crisis

7
Sebastian Meine

@@Identityの問題を明確にするには:

たとえば、テーブルを挿入し、そのテーブルに挿入を実行するトリガーがある場合、@@Identityはトリガーの挿入からID(log_idまたは何か)を返し、scope_identity()は元のテーブルの挿入からのID。

したがって、トリガーがない場合、scope_identity()@@identityは同じ値を返します。トリガーがある場合は、どの値が必要かを考える必要があります。

6
Jonas Lincoln

からの別の良い説明があります:

SCOPE_IDENTITYと@@ IDENTITYの違いについては、3つのステートメントを持つストアドプロシージャP1があるとします。
-新しいID値を生成するINSERT
-新しいID値を生成するINSERTステートメントも含むストアドプロシージャP2の呼び出し
-関数SCOPE_IDENTITYおよび@@ IDENTITYを照会するステートメントSCOPE_IDENTITY関数は、P1によって生成された値を返します(同じセッションとスコープ)。 @@ IDENTITY関数は、P2によって生成された値を返します(スコープに関係なく同じセッション)。

3
Dmitriy Dokshin

Scope Identity:実行中のストアドプロシージャ内に追加された最後のレコードのID。

@@Identity:クエリバッチ内、またはクエリの結果として追加された最後のレコードのID。挿入を実行するプロシージャ、トリガーを起動し、レコードを挿入すると、挿入されたレコードのIDがトリガーから返されます。

IdentCurrent:テーブルに割り当てられた最後のID。

3
Andrew