2

これについては完全なボトルではありませんが、@@IDENTITY は、どこにいても、データベースで最後に作成された ID の値を与えるという印象を受けました。SCOPE_IDENTITY() は、現在のステートメントのスコープ内の値を提供します。

ID列を持つテーブルがあります。トリガーはなく、バニラ テーブルとプライマリ インデックスのみです。この Web アプリ コードを 2 つの個別のブラウザー タブで実行しました。

Dim connDb As New SqlConnection(myconnectionstring)
Dim transDb As SqlTransaction = connDb.BeginTransaction()
Dim cmdInsert As New SqlCommand("INSERT INTO mytable (somecolumn) VALUES (somevalue)", conn, transDb)
Dim cmdGetIdentity As New SqlCommand("SELECT @@IDENTITY", connDb, transDb)
' Add the record, pause, get identity.
Dim iNewHosp As Int32 = cmdInsert.ExecuteNonQuery() ' Returns 1 correctly.
Threading.Thread.Sleep(5000) ' Give the other tab time to add a record.
Dim iNewID As Int32 = cmdGetIdentity.ExecuteScalar ' Returns the new ID.
' Commit trans, close, dispose, etc..

これはすべてトランザクション内で行われることに注意してください。それが違いを生むかどうかはわかりません。ここでは SQL Server 2000 を使用しています (残念ながら)。SQL2008でも試してみましたが、同じことが起こります。

そのため、ブラウザの 1 つのタブでページを実行し、スリープ中に別のタブで再度実行すると、別のレコードが追加されます。私が見ている「問題」は、最初のタブが他のタブと同様に、その INSERT に対して正しいID を返すことです。最初のタブは最新の挿入の ID を返すと思いました。2番目のタブで行われたもの?

私はもともとこれに SCOPE_IDENTITY() を使用しようとしましたが、NULL を返していたので、何が起こっているのかを確認するためだけに @@IDENTITY を試しました。2 つの質問があります。なぜ SCOPE_ は NULL を返すのでしょうか? @@IDENTITY はなぜスコープ固有の結果を返すのでしょうか?

4

2 に答える 2

4

いいえ、@@IDENTITY同じセッション内で生成されたID値に制限されます。の説明を参照してくださいSCOPE_IDENTITY

SCOPE_IDENTITY現在のセッション@@IDENTITYの任意のテーブルで生成された最後のID値を返します。ただし、現在のスコープ内にのみ挿入された値を返します。特定の範囲に限定されません。SCOPE_IDENTITY@@IDENTITY

(強調追加)

スコープ≠セッション。ここで、スコープとは、トリガー内で@@IDENTITY生成されたID値を返すなどを指します。INSERTご覧のとおり、最後のオプションはIDENT_CURRENT、セッションに関係なく、特定のテーブルの最新のID値をクエリできるようにすることです。

于 2012-05-17T08:32:24.010 に答える
0

Transacationでレコードの挿入を行っているため、SCOPE_IDENTITYそのtransacationに限定されます。したがって、他のトランザクションから挿入された値を確認することはできません。

2番目のタブでトランザクションがコミットされると、2番目のタブによって挿入されたIDを確認できます。

SELECT SCOPE_IDENTITY()

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

于 2012-05-17T08:35:31.917 に答える