次の方法で共有


SR0008: @@IDENTITY ではなく SCOPE_IDENTITY の使用を検討してください

RuleId

SR0008

カテゴリ

Microsoft.Design

互換性に影響する変更点

なし

原因

コードに @@IDENTITY 呼び出しが含まれています。

規則の説明

@@IDENTITY はグローバルな ID 値であるため、現在のスコープ外で更新され、予期しない値が取得されることがあります。 レプリケーションで使用される入れ子になったトリガを含め、トリガを行うと、現在のスコープ外で @@IDENTITY を更新することになります。

違反の修正方法

この問題を解決するには、@@IDENTITY への参照を、ユーザー ステートメントのスコープ内で最後に使用した ID 値を返す SCOPE_IDENTITY に置き換える必要があります。

警告を抑制する状況

他の処理で @@IDENTITY の値が更新されていないことが確実なときに @@IDENTITY を使用するステートメントを使用している場合は、この警告を抑制してもかまいません。 ただし、SCOPE_IDENTITY を使用すると目的の値が提供され、予期せず変更される危険性がないため、警告は抑制するのではなく解決することをお勧めします。

使用例

最初の例では、テーブルにデータを挿入するストアド プロシージャに @@IDENTITY が使用されています。 次に、テーブルがマージ レプリケーション用に発行され、発行されたテーブルにトリガが追加されます。 このため、@@IDENTITY は、ユーザー テーブルへの挿入操作の代わりに、レプリケーション システム テーブルへの挿入操作から値を返すことができます。

Sales.Customer テーブルの最大の ID 値は 29483 です。テーブルに行を挿入すると、@@IDENTITY と SCOPE_IDENTITY() は異なる値を返します。 SCOPE_IDENTITY() はユーザー テーブルへの挿入操作から値を返し、@@IDENTITY はレプリケーション システム テーブルへの挿入操作から値を返します。

2 番目の例は、挿入された ID にアクセスするために SCOPE_IDENTITY() を使用し、警告の問題を解決する方法を示しています。

CREATE PROCEDURE [dbo].[ProcedureWithWarning]
@param1 INT, 
@param2 NCHAR(1),
@Param3 INT OUTPUT
AS
BEGIN
INSERT INTO Sales.Customer ([TerritoryID],[CustomerType]) VALUES (@param1,@param2);

SELECT @Param3 = @@IDENTITY
END

CREATE PROCEDURE [dbo].[ProcedureFixed]
@param1 INT, 
@param2 NCHAR(1),
@param3 INT OUTPUT
AS
BEGIN
INSERT INTO Sales.Customer ([TerritoryID],[CustomerType]) VALUES (@param1,@param2);

SELECT @Param3 = @@SCOPE_IDENTITY()
END

参照

概念

スタティック分析によるデータベース コードの改善