1

厳密に現在のセッションでは、特定のテーブルに最後に挿入された行を取得する必要があります。使用できません。ANYテーブルに最後に挿入されたIDが返されるためです@@IDENTITYSCOPE_IDENTITY()の問題IDENT_CURRENTは、特定のテーブルに対して、ただし任意のセッションに対して、レコードの最後に挿入されたIDを返すことです。は複数のセッションによって呼び出されるため、これは私にとって問題ですINSERT。特定のセッションで最後に挿入されたレコードのIDが特に必要です。

これを達成する方法についての指針はありますか?

ps。ステートメントはSPROC内にINSERTないため、SPROCソリューションは実行可能ではありません。

ありがとう

4

1 に答える 1

6

あなたが聞きたいと思われる答えではないことは知っていますが、答えはを使用することSCOPE_IDENTITY()です。あなたが考えている問題(どのテーブルでもそうなるでしょう)は、なぜ私たちがSCOPE_IDENTITY()の代わりに使うのかということです@@IDENTITYIDENTITY列のあるテーブルがあり、そのテーブルに挿入トリガーがあり、それ自体が列のあるテーブルに挿入される場合を考えてみIDENTITYます。

CREATE TABLE dbo.Log(LogID INT IDENTITY(100,1), FooID INT);

CREATE TABLE dbo.Foo(FooID INT IDENTITY(1,1), name VARCHAR(32));
GO

CREATE TRIGGER dbo.Foo_Insert
ON dbo.Foo
FOR INSERT
AS
BEGIN
  SET NOCOUNT ON;
  INSERT dbo.Log(FooID) SELECT FooID FROM inserted;
END
GO

さて、あなたの状況は、挿入後にIDを取得するための信頼できる方法が必要な場合です。SCOPE_IDENTITY()これは、スコープに制限されているため、スコープに制限されていないためです(つまり、スコープではなく、トリガーのスコープで発生した@@IDENTITY最後に発行されたものを取得します。IDENTITY

INSERT dbo.Foo(name) SELECT 'Bob';

SELECT
  @@IDENTITY,
  SCOPE_IDENTITY();

結果:

----  ----
100   1

複数の行を挿入する場合は、どちらSCOPE_IDENTITY()も使用しないでください。@@IDENTITYこれを行う方法は、OUTPUT句を使用することです。まず、トリガーをドロップしましょう。

DROP TRIGGER dbo.Foo_Insert;

次に、複数行の挿入をテストしてみましょう。

  INSERT dbo.Foo(name) 
    OUTPUT inserted.FooID, inserted.name
    SELECT 'Frank' UNION ALL SELECT 'Jim';

結果:

FooID  name
-----  -----
2      Frank
3      Jim

条件付き挿入がある場合、違いはありません。持っているテーブルを維持しながら、このコードを2回試してみましょう。

DECLARE @table SYSNAME;
SET @table = N'Log';

IF @table = N'Log'
BEGIN
    INSERT dbo.Log(FooID) SELECT 10;
END

IF @table = N'Foo'
BEGIN
    INSERT dbo.Foo(name) SELECT 'Tom';
END

SELECT SCOPE_IDENTITY();

結果:

----
101

でもう一度試してみましょうN'Foo'

DECLARE @table SYSNAME;
SET @table = N'Foo';

IF @table = N'Log'
BEGIN
INSERT dbo.Log(FooID) SELECT 10;
END

IF @table = N'Foo'
BEGIN
    INSERT dbo.Foo(name) SELECT 'Tom';
END

SELECT SCOPE_IDENTITY();

結果:

----
4

それよりも複雑な場合(たとえば、複数のテーブルに挿入する場合)、次のようなことができます。

IF <some conditional>
BEGIN
    INSERT dbo.sometable ...
    SET @somevar = SCOPE_IDENTITY();
END
IF <some other conditional>
BEGIN
    INSERT dbo.some_other_table ...
    SET @some_other_var = SCOPE_IDENTITY();
END

なぜこれが機能しないと思うのかわかりません。また、機能することを納得させるために、なぜこの長さに行かなければならないのかわかりません。繰り返しになりますが、これが機能しない例(または、干渉すると思われる「任意のテーブル」)を示すと、コメントできる可能性があります。現状では、あなたの意見はSCOPE_IDENTITY()あなたが聞いたことに基づいているように思えます@@IDENTITY。これらの仮定は、自分自身を証明または反証するのは非常に簡単です。

余談ですIDENT_CURRENTが、この会話では言及されるべきではありません。並行アクティビティに使用することはまったく安全ではありません。私に関する限り、聞いたことがないふりをする必要があります。トリガーの外側から、トリガーの内側で生成された@@IDENTITYものを本当にキャプチャしたい場合を除いて、これの有効な使用法は考えられません。IDENTITY

于 2012-07-01T18:48:35.893 に答える