次の方法で共有


バルク コピー操作の単一実行 (ADO.NET)

SQL Server のバルク コピー操作を実行する簡単な方法は、データベースに対して単一操作を実行することです。 既定では、バルク コピー操作は分離された操作として実行されます。このコピー操作は非トランザクション方式で処理され、ロールバックできません。

メモメモ

エラーの発生時に、バルク コピー処理の全部または一部をロールバックする必要がある場合は、SqlBulkCopy が管理するトランザクションを使用するか、または既存のトランザクション内でバルク コピー操作を実行できます。SqlBulkCopy は、System.Transactions トランザクションに (明示的または暗黙的に) 接続が参加している場合は System.Transactions も使用します。

詳細については、「トランザクションとバルク コピー操作 (ADO.NET)」を参照してください。

通常、バルク コピー操作の実行手順は次のようになります。

  1. コピー元のサーバーに接続し、コピーするデータを取得します。 IDataReader オブジェクトまたは DataTable オブジェクトからデータを取得できる場合は、他のソースからデータを取得して利用することもできます。

  2. コピー先のサーバーに接続します (SqlBulkCopy を使用して接続を確立しない場合)。

  3. SqlBulkCopy オブジェクトを作成し、必要なプロパティを設定します。

  4. バルク挿入操作の対象となるテーブルが示されるように DestinationTableName プロパティを設定します。

  5. WriteToServer メソッドのいずれかを呼び出します。

  6. オプションとして、プロパティを更新したり、必要に応じて WriteToServer をもう一度呼び出したりします。

  7. Close を呼び出すか、または Using ステートメント内にバルク コピー操作をラップします。

Caution メモ注意

コピー元とコピー先の列のデータ型を一致させることをお勧めします。データ型が一致していない場合、SqlBulkCopy は、Value によって採用されている規則を使用して、コピー元の値をコピー先のデータ型にそれぞれ変換しようとします。この変換はパフォーマンスに影響を及ぼし、予期しないエラーが発生することもあります。たとえば、Double データ型は、多くの場合 Decimal データ型に変換されますが、常にというわけではありません。

次のコンソール アプリケーションでは、SqlBulkCopy クラスを使用してデータを読み込む方法について示しています。 この例では、SqlDataReader を使用し、SQL Server 2005 の AdventureWorks データベースに格納された Production.Product テーブルのデータを、同じデータベース内の同等のテーブルにコピーします。

重要 :重要

このサンプルを実行するには、あらかじめ、「バルク コピー サンプルのセットアップ (ADO.NET)」の説明に従って作業テーブルを作成しておく必要があります。このコードでは、SqlBulkCopy だけを使用した構文について説明します。コピー元およびコピー先のテーブルが同一の SQL Server インスタンス内に存在する場合、Transact-SQL の INSERT … SELECT ステートメントを使用すれば簡単かつ高速にデータをコピーすることができます。

Imports System.Data.SqlClient

Module Module1
    Sub Main()
        Dim connectionString As String = GetConnectionString()

        ' Open a connection to the AdventureWorks database.
        Using sourceConnection As SqlConnection = _
           New SqlConnection(connectionString)
            sourceConnection.Open()

            ' Perform an initial count on the destination table.
            Dim commandRowCount As New SqlCommand( _
            "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", _
                sourceConnection)
            Dim countStart As Long = _
               System.Convert.ToInt32(commandRowCount.ExecuteScalar())
            Console.WriteLine("Starting row count = {0}", countStart)

            ' Get data from the source table as a SqlDataReader.
            Dim commandSourceData As SqlCommand = New SqlCommand( _
               "SELECT ProductID, Name, ProductNumber " & _
               "FROM Production.Product;", sourceConnection)
            Dim reader As SqlDataReader = commandSourceData.ExecuteReader

            ' Open the destination connection. In the real world you would 
            ' not use SqlBulkCopy to move data from one table to the other   
            ' in the same database. This is for demonstration purposes only.
            Using destinationConnection As SqlConnection = _
                New SqlConnection(connectionString)
                destinationConnection.Open()

                ' Set up the bulk copy object. 
                ' The column positions in the source data reader 
                ' match the column positions in the destination table, 
                ' so there is no need to map columns.
                Using bulkCopy As SqlBulkCopy = _
                  New SqlBulkCopy(destinationConnection)
                    bulkCopy.DestinationTableName = _
                    "dbo.BulkCopyDemoMatchingColumns"

                    Try
                        ' Write from the source to the destination.
                        bulkCopy.WriteToServer(reader)

                    Catch ex As Exception
                        Console.WriteLine(ex.Message)

                    Finally
                        ' Close the SqlDataReader. The SqlBulkCopy
                        ' object is automatically closed at the end
                        ' of the Using block.
                        reader.Close()
                    End Try
                End Using

                ' Perform a final count on the destination table
                ' to see how many rows were added.
                Dim countEnd As Long = _
                    System.Convert.ToInt32(commandRowCount.ExecuteScalar())
                Console.WriteLine("Ending row count = {0}", countEnd)
                Console.WriteLine("{0} rows were added.", countEnd - countStart)

                Console.WriteLine("Press Enter to finish.")
                Console.ReadLine()
            End Using
        End Using
    End Sub

    Private Function GetConnectionString() As String
        ' To avoid storing the sourceConnection string in your code, 
        ' you can retrieve it from a configuration file. 
        Return "Data Source=(local);" & _
            "Integrated Security=true;" & _
            "Initial Catalog=AdventureWorks;"
    End Function
End Module
using System.Data.SqlClient;

class Program
{
    static void Main()
    {
        string connectionString = GetConnectionString();
        // Open a sourceConnection to the AdventureWorks database.
        using (SqlConnection sourceConnection =
                   new SqlConnection(connectionString))
        {
            sourceConnection.Open();

            // Perform an initial count on the destination table.
            SqlCommand commandRowCount = new SqlCommand(
                "SELECT COUNT(*) FROM " +
                "dbo.BulkCopyDemoMatchingColumns;",
                sourceConnection);
            long countStart = System.Convert.ToInt32(
                commandRowCount.ExecuteScalar());
            Console.WriteLine("Starting row count = {0}", countStart);

            // Get data from the source table as a SqlDataReader.
            SqlCommand commandSourceData = new SqlCommand(
                "SELECT ProductID, Name, " +
                "ProductNumber " +
                "FROM Production.Product;", sourceConnection);
            SqlDataReader reader =
                commandSourceData.ExecuteReader();

            // Open the destination connection. In the real world you would 
            // not use SqlBulkCopy to move data from one table to the other 
            // in the same database. This is for demonstration purposes only.
            using (SqlConnection destinationConnection =
                       new SqlConnection(connectionString))
            {
                destinationConnection.Open();

                // Set up the bulk copy object. 
                // Note that the column positions in the source
                // data reader match the column positions in 
                // the destination table so there is no need to
                // map columns.
                using (SqlBulkCopy bulkCopy =
                           new SqlBulkCopy(destinationConnection))
                {
                    bulkCopy.DestinationTableName =
                        "dbo.BulkCopyDemoMatchingColumns";

                    try
                    {
                        // Write from the source to the destination.
                        bulkCopy.WriteToServer(reader);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                    finally
                    {
                        // Close the SqlDataReader. The SqlBulkCopy
                        // object is automatically closed at the end
                        // of the using block.
                        reader.Close();
                    }
                }

                // Perform a final count on the destination 
                // table to see how many rows were added.
                long countEnd = System.Convert.ToInt32(
                    commandRowCount.ExecuteScalar());
                Console.WriteLine("Ending row count = {0}", countEnd);
                Console.WriteLine("{0} rows were added.", countEnd - countStart);
                Console.WriteLine("Press Enter to finish.");
                Console.ReadLine();
            }
        }
    }

    private static string GetConnectionString()
        // To avoid storing the sourceConnection string in your code, 
        // you can retrieve it from a configuration file. 
    {
        return "Data Source=(local); " +
            " Integrated Security=true;" +
            "Initial Catalog=AdventureWorks;";
    }
}

Transact-SQL および Command クラスを使用したバルク コピー操作の実行

SqlBulkCopy クラスがサポートされていない、バージョン 1.1 以前の .NET Framework では、SqlCommand オブジェクトを使用して、Transact-SQL の BULK INSERT ステートメントを実行できます。 このテクニックの使用は、.NET Framework Data Provider for SQL Server によって提供されているバルク コピー機能の使用とはまったく関連性がありません。

次の例では、BULK INSERT ステートメントを実行する ExecuteNonQuery メソッドの使用方法を説明します。

メモメモ

データ ソースのファイル パスはサーバーに対する相対パスです。サーバー プロセスがこのパスにアクセスできないと、バルク コピー操作は失敗します。

Using connection As SqlConnection = New SqlConnection(connectionString)
Dim queryString As String = _
    "BULK INSERT Northwind.dbo.[Order Details] FROM " & _
    "'f:\mydata\data.tbl' WITH (FORMATFILE='f:\mydata\data.fmt' )"
connection.Open()
SqlCommand command = New SqlCommand(queryString, connection);

command.ExecuteNonQuery()
End Using
using (SqlConnection connection = New SqlConnection(connectionString))
{
string queryString =  "BULK INSERT Northwind.dbo.[Order Details] " +
    "FROM 'f:\mydata\data.tbl' " +
    "WITH ( FORMATFILE='f:\mydata\data.fmt' )";
connection.Open();
SqlCommand command = new SqlCommand(queryString, connection);

command.ExecuteNonQuery();
}

参照

その他の技術情報

SQL Server でのバルク コピー操作 (ADO.NET)