Language

一括コピー操作の単一実行

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

注

エラー発生後に一括コピーの全部または一部をロールバックするには、バッチごとのトランザクションで SqlBulkCopyOptions.UseInternalTransaction を指定するか、既存のトランザクション内でコピーを実行してください。 SqlBulkCopy は、System.Transactions との接続が暗黙的または明示的に登録されている場合にも動作します。

詳細については、「トランザクションと一括コピー操作」を参照してください。

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

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

  2. 移行先サーバーに接続します (ただし、SqlBulkCopy が接続を確立するのを望む場合を除きます)。

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

  4. 一括挿入操作のターゲット テーブルを示すように、 DestinationTableName プロパティを設定します。

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

  6. 必要に応じて、プロパティを更新し、必要に応じて WriteToServer を再度呼び出します。

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

注意事項

一致するソースとターゲットの列のデータ型を使用します。 型が一致しない場合、 SqlBulkCopy は、 Valueの規則を使用して、各ソース値をターゲット データ型に変換しようとします。 変換はパフォーマンスに影響し、予期しないエラーが発生する可能性があります。 たとえば、 Double から Decimal への変換は、一部の値で失敗する可能性があります。

例

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

重要

このサンプルを実行する前に、一括コピーの例のセットアップで説明されている作業テーブルを作成してください。 このサンプルは、SqlBulkCopy の構文を示しています。 コピー元テーブルとコピー先テーブルが同じSQL Server インスタンスにある場合は、Transact-SQL (T-SQL) INSERT ... SELECT ステートメントを使用してコピーを高速化します。

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

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

        // Get data from the source table as a SqlDataReader.
        SqlCommand commandSourceData = new(
            "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(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(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 = Convert.ToInt32(
                commandRowCount.ExecuteScalar());
            Console.WriteLine($"Ending row count = {countEnd}");
            Console.WriteLine($"{countEnd - countStart} rows were added.");
            Console.WriteLine("Press Enter to finish.");
            Console.ReadLine();
        }
    }
}
Imports Microsoft.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 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
        Throw New NotImplementedException()
    End Function
End Module

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

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

注

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

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()
Dim command As 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();
}

関連項目