sql - 使い方 - 挿入された行のIDを取得する最も良い方法は?
sqlserver insert identity 取得 (8)
Entity Frameworkを使用する場合は、内部的にOUTPUT
技法を使用して、新しく挿入されたID値を返します
DECLARE @generated_keys table([Id] uniqueidentifier)
INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
VALUES('Malleable logarithmic casing');
SELECT t.[TurboEncabulatorID ]
FROM @generated_keys AS g
JOIN dbo.TurboEncabulators AS t
ON g.Id = t.TurboEncabulatorID
WHERE @@ROWCOUNT > 0
出力結果は一時テーブル変数に格納され、テーブルに再び結合され、テーブルから行の値が返されます。
注:EFが実際のテーブルに戻ってエフェメラルテーブルを結合する理由がわかりません。
しかし、それがEFの役割です。
この手法( OUTPUT
)は、SQL Server 2008以降でのみ使用できます。
挿入された行のIDENTITY
を取得する最も良い方法は何ですか?
私は@@IDENTITY
とIDENT_CURRENT
とSCOPE_IDENTITY
について知っていますが、それぞれに付いている長所と短所を理解していません。
誰かが違いを説明して、私がそれぞれを使用しなければならない時を教えてください。
@@ IDENTITY、SCOPE_IDENTITY、およびIDENT_CURRENTは、表のIDENTITY列に最後に挿入された値を戻す点で同じです。
@@ IDENTITYおよびSCOPE_IDENTITYは、現在のセッションの任意のテーブルで生成された最後のID値を返します。 ただし、SCOPE_IDENTITYは現在のスコープ内の値のみを返します。 @@ IDENTITYは特定のスコープに限定されません。
IDENT_CURRENTはスコープとセッションによって制限されません。 指定された表に限定されています。 IDENT_CURRENTは、任意のセッションおよびスコープ内の特定の表に対して生成されたID値を戻します。 詳細は、IDENT_CURRENTを参照してください。
- IDENT_CURRENTは、テーブルを引数として取る関数です。
- MSDNは、テーブルにトリガがあると混乱した結果を返すことがあります
- SCOPE_IDENTITYはあなたの大SCOPE_IDENTITYです。
常にscope_identity()を使用してください。他に何も必要はありません。
挿入されたIDを取得する最も安全で正確な方法は、出力句を使用することです。
たとえば、次のMSDN記事から取得します。
USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table( NewScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO @MyTableVar
VALUES (N'Operator error', GETDATE());
--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason;
GO
新しく挿入された行のIDを取得するには、 output
句を使用するのがベストです(最も安全な方法:最も安全です)。
create table TableWithIdentity
( IdentityColumnName int identity(1, 1) not null primary key,
... )
-- type of this table's column must match the type of the
-- identity column of the table you'll be inserting into
declare @IdentityOutput table ( ID int )
insert TableWithIdentity
( ... )
output inserted.IdentityColumnName into @IdentityOutput
values
( ... )
select @IdentityValue = (select ID from @IdentityOutput)
私は他のバージョンのSQL Serverと話すことはできませんが、2012年には直接出力するだけで問題ありません。 あなたは一時的なテーブルを気にする必要はありません。
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)
ちなみに、このテクニックは、複数の行を挿入するときにも機能します。
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
(...),
(...),
(...)
出力
ID
2
3
4
追加
SELECT CAST(scope_identity() AS int);
insert sql文の最後まで
NewId = command.ExecuteScalar()
それを取得します。
@@IDENTITY
は、現在のセッション内の任意のテーブルに対して生成された最後のID値をすべてのスコープにわたって返します。 それはスコープを越えているので、 ここで注意する必要があります 。 現在のステートメントではなく、トリガーから値を取得できます。SCOPE_IDENTITY()
は、現在のセッション内の任意のテーブルおよび現在のスコープに対して生成された最後のID値を返します。 一般的にあなたが使いたいものです 。IDENT_CURRENT('tableName')
は、任意のセッションおよびスコープ内の特定のテーブルに対して生成された最後のID値を返します。 これにより、上記の2つのテーブルが必要なものではない場合( 非常に稀です )に、値を使用するテーブルを指定できます。 また、@ Guy Starbuck氏は、「レコードを挿入していないテーブルの現在のIDENTITY値を取得したい場合は、これを使用できます。INSERT
ステートメントのOUTPUT
節は、そのステートメントを介して挿入されたすべての行にアクセスできるようにします。 特定のステートメントに限定されているので、上記の他の関数よりも簡単です。 しかし、もう少し冗長です (テーブルの変数/一時テーブルに挿入してからクエリを実行する必要があります)、ステートメントがロールバックされるエラーシナリオでも結果が得られます。 つまり、クエリでパラレル実行プランが使用されている場合、これはIDを取得するための唯一の保証された方法です(並列性をオフにするのには不十分です)。 ただし、トリガの前に実行され、トリガ生成の値を返すために使用することはできません。