web-dev-qa-db-ja.com

@@ IDENTITY、SCOPE_IDENTITY()、OUTPUT、および最後のIDを取得するその他の方法

挿入後に主キーIDフィールドの値を取得するときに使用されるさまざまなメソッドを見てきました。

declare @t table (
    id int identity primary key,
    somecol datetime default getdate()
)
insert into @t
default values

select SCOPE_IDENTITY() --returns 1
select @@IDENTITY --returns 1

挿入後にIDのテーブルを返す:

Create Table #Testing (  
    id int identity,  
    somedate datetime default getdate()  
)  
insert into #Testing  
output inserted.*  
default values   

どの方法が適切ですか? OUTPUTメソッドはスコープセーフですか?

2番目のコードスニペットは、 SQL in the Wild

57
Seibar

それはあなたが何をしようとしているかに依存します...

@@身元

値を生成したテーブル、および値を生成したステートメントのスコープに関係なく、接続で生成された最後のIDENTITY値を返します。 @@ IDENTITYは、現在のセッションでテーブルに入力された最後のID値を返します。 @@ IDENTITYは現在のセッションに限定され、現在のスコープに限定されません。たとえば、別のテーブルにIDを作成するトリガーがテーブルにある場合、それが作成されたトリガーであっても、最後に作成されたIDを取得します。

SCOPE_IDENTITY()

値を生成したテーブルに関係なく、接続および同じスコープ内のステートメントによって生成された最後のIDENTITY値を返します。 SCOPE_IDENTITY()は@@ IDENTITYに似ていますが、現在のスコープに値を制限します。つまり、トリガーまたはユーザー定義関数によって作成されたIDではなく、明示的に作成した最後のID値を返します。

IDENT_CURRENT()

値を生成したステートメントの接続とスコープに関係なく、テーブルで生成された最後のIDENTITY値を返します。 IDENT_CURRENTは指定されたテーブルに制限されますが、接続またはスコープによって制限されません。

72
mson

scope_identity()および@@identityにバグがあることに注意してください-MS Connectを参照してください: https://connect.Microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=328811

引用(Microsoftから):

すべての場合において、@@IDENTITYの代わりにOUTPUTを使用することを強くお勧めします。これは、IDとタイムスタンプを読み取るための最良の方法です。

追加して編集:これは現在修正されている可能性があります。 Connectでエラーが表示されますが、以下を参照してください。

Scope_Identity()が間違った値を返しましたか?

12
Simon D

挿入された行のIDを取得しようとするときに、OUTPUT句以外に何かを使用する理由はほとんどありません。 OUTPUT句はスコープとテーブルに対して安全です。

単一の行を挿入した後にIDを取得する簡単な例を次に示します...

DECLARE @Inserted AS TABLE (MyTableId INT);

INSERT [MyTable] (MyTableColOne, MyTableColTwo)
OUTPUT Inserted.MyTableId INTO @Inserted
VALUES ('Val1','Val2')

SELECT MyTableId FROM @Inserted

OUTPUT句の詳細なドキュメント: http://technet.Microsoft.com/en-us/library/ms177564.aspx


-- table structure for example:     
CREATE TABLE MyTable (
    MyTableId int NOT NULL IDENTITY (1, 1),
    MyTableColOne varchar(50) NOT NULL,
    MyTableColTwo varchar(50) NOT NULL
)
8
JeremyWeir

@@ Identityは古い方法です。今後すべてのインスタンスでSCOPE_IDENTITY()を使用します。 @ -IDENTITYの使用の影響については [〜#〜] msdn [〜#〜] を参照してください(これらは悪い!)。

6
jcollum

SCOPE_IDENTITYは単一行に十分であり、何らかの理由で中間TRIGGERの結果を表示する必要がある場合を除いて推奨されます(理由)。

複数の行の場合、OUTPUT/OUTPUT INTOは新しい親友であり、行を再検索して別のテーブルに挿入する代わりになります。

4
Cade Roux

SQL in the Wild で概説されているSQL Server 2005で利用可能な別の方法があります。

これにより、挿入後に複数のIDを取得できます。ブログ投稿のコードは次のとおりです。

Create Table #Testing (  
    id int identity,  
    somedate datetime default getdate()  
)  
insert into #Testing  
output inserted.*  
default values
3
Seibar

Godekeの答えに対する小さな修正:

心配する必要のあるトリガーだけではありません。ストアドプロシージャなど、識別子を作成するあらゆる種類のネストされた操作は、@@ IDENTITYの値を変更する可能性があります。

Scope_identityへの別の投票...

3
Paul Sasik

@@ IDENTITYの使用中は注意してください...

http://dotnetgalactics.wordpress.com/2009/10/28/scope-identity-vs-identity/

1
Pato