@@IDENTITY 関数 vs SCOPE_IDENTITY() 関数 vs IDENT_CURRENT() 関数: ID 値を取得する最適な方法は?

2024-04-10

SQL Server 2005 では、INSERT ステートメントの OUTPUT 句を使用して、自動生成された ID 値を含む挿入された行の情報を取り出すことができます。これは、@@IDENTITY 関数や SCOPE_IDENTITY() 関数を使用するよりも効率的で信頼性の高い方法です。

方法

以下の手順で、OUTPUT 句を使用して ID 値を取得できます。

  1. INSERT ステートメントを作成します。
  2. OUTPUT 句を追加します。
  3. OUTPUT 句によって返される結果セットから ID 値を取得します。

以下の例では、Customers テーブルに新しい顧客を挿入し、OUTPUT 句を使用して自動生成された ID 値を取得します。

INSERT INTO Customers (FirstName, LastName)
OUTPUT INSERTED.CustomerID
VALUES ('John', 'Doe');

この例では、OUTPUT 句によって返される結果セットには、1 つの列 (CustomerID) が含まれます。この列には、挿入された行の ID 値が含まれます。

ID 値の取得

OUTPUT 句によって返される結果セットは、SELECT ステートメントの結果セットと同様に処理できます。ID 値を取得するには、以下の方法を使用できます。

  • LINQ
var context = new MyContext();

var customer = new Customer
{
    FirstName = "John",
    LastName = "Doe"
};

context.Customers.Add(customer);
context.SaveChanges();

var customerId = customer.CustomerID;
  • ADO.NET
using (var connection = new SqlConnection("..."))
{
    using (var command = new SqlCommand("INSERT INTO Customers (FirstName, LastName) OUTPUT INSERTED.CustomerID VALUES (@FirstName, @LastName)", connection))
    {
        command.Parameters.AddWithValue("@FirstName", "John");
        command.Parameters.AddWithValue("@LastName", "Doe");

        connection.Open();

        var customerId = (int)command.ExecuteScalar();
    }
}

利点

OUTPUT 句を使用する方法は、@@IDENTITY 関数や SCOPE_IDENTITY() 関数を使用するよりもいくつかの利点があります。

  • 効率性

OUTPUT 句は、@@IDENTITY 関数や SCOPE_IDENTITY() 関数よりも効率的です。これは、OUTPUT 句は 1 つのクエリで ID 値を取得できるためです。一方、@@IDENTITY 関数や SCOPE_IDENTITY() 関数は、2 つのクエリが必要です。

  • 信頼性

OUTPUT 句は、SQL Server 2005 の INSERT ステートメントで自動生成された ID 値を取得するための効率的で信頼性の高い方法です。




C#

using System;
using System.Data.SqlClient;

namespace OutputClauseExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // 接続文字列
            const string connectionString = "Data Source=localhost;Initial Catalog=Test;Integrated Security=True";

            // INSERT ステートメント
            const string sql = @"
                INSERT INTO Customers (FirstName, LastName)
                OUTPUT INSERTED.CustomerID
                VALUES (@FirstName, @LastName)";

            // パラメータ
            var parameters = new SqlParameter[]
            {
                new SqlParameter("@FirstName", "John"),
                new SqlParameter("@LastName", "Doe")
            };

            // SqlConnection オブジェクトを作成
            using (var connection = new SqlConnection(connectionString))
            {
                // SqlCommand オブジェクトを作成
                using (var command = new SqlCommand(sql, connection))
                {
                    // パラメータを追加
                    command.Parameters.AddRange(parameters);

                    // コマンドを開く
                    connection.Open();

                    // INSERT ステートメントを実行
                    var customerId = (int)command.ExecuteScalar();

                    // 結果を出力
                    Console.WriteLine("CustomerID: {0}", customerId);
                }
            }
        }
    }
}

SQL

INSERT INTO Customers (FirstName, LastName)
OUTPUT INSERTED.CustomerID
VALUES ('John', 'Doe');

実行結果

CustomerID: 1

説明

  1. 最初に、SqlConnection オブジェクトを作成して、データベースへの接続を開きます。
  2. 次に、SqlCommand オブジェクトを作成して、INSERT ステートメントを指定します。
  3. INSERT ステートメントのパラメータとして、FirstNameLastName の値を指定します。
  4. SqlCommand オブジェクトの ExecuteScalar() メソッドを使用して、INSERT ステートメントを実行します。
  5. ExecuteScalar() メソッドによって返される値は、挿入された行の ID 値です。
  6. 最後に、ID 値を出力します。

補足

このサンプルコードは、基本的な例です。実際には、さまざまな方法で OUTPUT 句を使用できます。詳細については、以下のリソースを参照してください。




ID 値を取得するその他の方法

@@IDENTITY 関数は、最後に挿入された行の ID 値を取得するために使用できます。

INSERT INTO Customers (FirstName, LastName)
VALUES ('John', 'Doe');

SELECT @@IDENTITY;
BEGIN TRAN

INSERT INTO Customers (FirstName, LastName)
VALUES ('John', 'Doe');

SELECT SCOPE_IDENTITY();

COMMIT TRAN

IDENT_CURRENT('table_name') 関数は、指定されたテーブルの最後に挿入された行の ID 値を取得するために使用できます。

INSERT INTO Customers (FirstName, LastName)
VALUES ('John', 'Doe');

SELECT IDENT_CURRENT('Customers');

これらの方法の比較

方法利点欠点
OUTPUT効率的並列実行プランでは誤った値を返す可能性がある
@@IDENTITY 関数シンプル並列実行プランでは誤った値を返す可能性がある
SCOPE_IDENTITY() 関数信頼性が高いトランザクション内で使用する必要がある
IDENT_CURRENT('table_name')汎用性が高いトランザクション内で使用する必要がない

OUTPUT 句は、SQL Server 2005 で自動生成された ID 値を取得するための効率的で信頼性の高い方法です。ただし、並列実行プランを使用している場合は、誤った値を返す可能性があります。他の方法は、それぞれ異なる利点と欠点があります。要件に応じて、適切な方法を選択する必要があります。


sql sql-server-2005 insert


SQL DISTINCT を使ってデータベースの2つのフィールドを区別する方法

SQL DISTINCT は、データベースから重複するレコードを除去するクエリで使用されるキーワードです。2つのフィールドを区別したい場合は、DISTINCT と共に ON 句を使用できます。例以下の例では、customers テーブルから重複する名前とメールアドレスの組み合わせを除去しています。...


SQL Serverで動的処理をレベルアップ:テーブル名を動的に扱うテクニック

上記のように、DECLARE ステートメントを用いて変数を宣言し、= 演算子でテーブル名を代入します。変数名は任意ですが、分かりやすい名前を推奨します。変数は、プロシージャや関数内でパラメータとして受け取り、処理に活用することもできます。この例では、GetCustomerData というプロシージャを作成し、@tableName というパラメータでテーブル名を指定できるようにしています。呼び出し時には、以下のように実行します。...


SQLite CREATE VIRTUAL TABLEコマンドで異なるデータベースのテーブルを結合

概要:ATTACH DATABASE コマンドを使用して、別のデータベースを現在のデータベースに一時的に接続し、テーブルを結合します。メリット:シンプルで使いやすい他の方法よりも高速接続するデータベースが同じファイルシステム上に存在する必要がある...


SQL WHERE 句で列エイリアスを使用するサンプルコード

SQL で SELECT 句で列エイリアスを定義した場合、WHERE 句でそのエイリアスを使用して列を参照することができます。これは、特に列名が長い場合や、複数のテーブルから同じ名前の列を選択する場合に役立ちます。方法WHERE 句で列エイリアスを参照するには、次の構文を使用します。...


SQL: SELECTとDELETEで異なるDATETIMEフィールドのフィルタリング挙動

SQLにおけるDATETIMEフィールドのフィルタリングは、SELECTとDELETE操作で微妙な違いがあります。この違いを理解することは、意図した結果を得るために重要です。SELECT操作では、WHERE句を使用してDATETIMEフィールドに基づいて行をフィルタリングできます。以下の例では、2024年6月28日以降のすべての行を選択しています。...


SQL SQL SQL SQL Amazon で見る



SCOPE_IDENTITY() を使用して挿入された行の ID を取得する方法

SQL Server で INSERT ステートメントを使用して行を挿入した後、その行の ID を取得する必要がある場合があります。この ID は、多くの場合、主キーとして使用されます。方法挿入された行の ID を取得するには、次の 3 つの方法があります。