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


191

私が知っているScope_Identity()Identity()@@Identity、およびIdent_Current()すべてのID列の値を取得するが、私は違いを知っているのが大好きです。

私が持っている論争の一部は、上記のこれらの関数に適用されるスコープによって何を意味するのですか?

また、それらを使用するさまざまなシナリオの簡単な例も気に入りましたか?


2
SCOPE_IDENTITYおよび@@ IDENTITYのSQL Serverに存在する並列実行のバグを忘れないでください:support.microsoft.com/default.aspx
David d C e Freitas

@DaviddCeFreitas-バグについて知りたいのですが、リンクが壊れているように見えます(少なくともASPエラーが発生しています)。
rory.ap 2015

2
実際、私はそれを見つけました:support.microsoft.com/en-us/kb/2019779
rory.ap 2015

その古いKB記事で言及されている修正がリリースされていました
ジョージ・ビルビリス

回答:


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

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

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

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


14
「scope_identity()と@@ identity ...」という段落があるため、これを答えとして選択しました。それは物事をより明確にした。
Tebo

1
上記のDavid Freitasが述べたように、scope_identityの実装にはバグがあるため、代わりの方法であるOUTPUT句の使用をお勧めします。以下の私の答えを参照してください。
Sebastian Meine、2012年

@Guffa-「セッションはデータベース接続です」。接続プールを使用している場合、セッションは接続間で維持されますか?
Dave Black

1
これはお手本の答えです。特に、SQLとSQL Serverの操作は奇妙な場合があります。これは、かなり有益でありながら、非常に明確で平凡な方法で説明しています。2つのデータベーススペシャリスト間でやり取りされているようなものではないように思われます。他のSEの回答の多くがそれを行います。
Panzercrisis

@DaveBlack私が読んだもの:いいえ、セッションはプールで維持されていません。セッションは、connect()の後にスクリプトを実行するために一意です。プール時... SQL ServerのPHPは、ODBC接続プールを使用します。プールからの接続が使用されると、接続状態がリセットされます。接続を閉じると、接続がプールに戻ります。(メモ:Linux / Mac用の注釈を参照してください)docs.microsoft.com/en-us/sql/connect/php/...
GDmac

42

良い質問。

  • @@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()


16

スコープとセッションの違いを理解していれば、これらの方法を理解するのは非常に簡単です。

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

セッションとは、コマンドを実行している現在の接続を意味します。

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

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

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

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

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


11

スコープとは、のグローバルスコープではなく、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 

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


9

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

詳細と例については、こちらをご覧ください:アイデンティティの危機


この答えはもっと注目に値すると思います。
cheeze

残念ながらINSERT ... OUTPUT Inserted.xxはINSERTトリガーでは機能しません(UPDATE ... OUTPUT Updated.xxとUPDATEトリガーも同様です)。彼らはINSERT ... OUTPUT INTOの使用を提案していますが、それは冗長すぎて、(ストアドプロシージャではなく)クライアントからの使用は問題があります。INSERT ... OUTPUT Inserted.xxは、トリガーが必要ない場合に、クライアント側の呼び出しで使用するときれいです(挿入を実行して、新しい行の自動生成されたIDを取得するには、ExecuteScalarが必要です)。
ジョージビルビリス

6

で問題を明確にするには@@Identity

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

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


4

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

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

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


3

これは本から別の良い説明です:

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.