Pojedyncze operacje kopiowania zbiorczego

Najprostszym podejściem do wykonywania operacji kopiowania zbiorczego programu SQL Server jest wykonanie pojedynczej operacji względem bazy danych. Domyślnie operacja kopiowania zbiorczego jest wykonywana jako izolowana operacja: operacja kopiowania odbywa się w sposób nieaktakowany, bez możliwości wycofywania.

Uwaga

Jeśli musisz wycofać całą lub część kopii zbiorczej po wystąpieniu błędu, możesz użyć transakcji zarządzanej SqlBulkCopylub wykonać operację kopiowania zbiorczego w ramach istniejącej transakcji. Narzędzie SqlBulkCopy będzie również działać, System.Transactions jeśli połączenie jest wymienione (niejawnie lub jawnie) w transakcji System.Transactions .

Aby uzyskać więcej informacji, zobacz Operacje transakcji i kopiowania zbiorczego.

Ogólne kroki wykonywania operacji kopiowania zbiorczego są następujące:

  1. Połączenie do serwera źródłowego i uzyskaj dane do skopiowania. Dane mogą również pochodzić z innych źródeł, jeśli można je pobrać z IDataReader obiektu lub DataTable .

  2. Połączenie do serwera docelowego (chyba że chcesz, aby narzędzie SqlBulkCopy nawiązało połączenie).

  3. SqlBulkCopy Utwórz obiekt, ustawiając wszelkie niezbędne właściwości.

  4. Ustaw właściwość DestinationTableName, aby wskazać tabelę docelową operacji wstawiania zbiorczego.

  5. Wywołaj jedną z metod WriteToServer .

  6. Opcjonalnie zaktualizuj właściwości i ponownie wywołaj metodę WriteToServer w razie potrzeby.

  7. Wywołaj Closemetodę lub opakuj operacje kopiowania zbiorczego w instrukcji Using .

Uwaga

Zalecamy dopasowanie typów danych kolumn źródłowych i docelowych. Jeśli typy danych nie są zgodne, narzędzie SqlBulkCopy próbuje przekonwertować każdą wartość źródłową na docelowy typ danych przy użyciu reguł stosowanych przez Valueprogram . Konwersje mogą wpływać na wydajność, a także powodować nieoczekiwane błędy. Na przykład Double typ danych można przekonwertować na Decimal typ danych przez większość czasu, ale nie zawsze.

Przykład

Poniższa aplikacja konsolowa pokazuje, jak ładować dane przy użyciu SqlBulkCopy klasy . W tym przykładzie element jest SqlDataReader używany do kopiowania danych z tabeli Production.Product w bazie danych SQL Server AdventureWorks do podobnej tabeli w tej samej bazie danych.

Ważne

Ten przykład nie zostanie uruchomiony, chyba że zostały utworzone tabele robocze zgodnie z opisem w sekcji Konfiguracja przykładu kopiowania zbiorczego. Ten kod jest dostarczany w celu zademonstrowania składni tylko przy użyciu narzędzia SqlBulkCopy . Jeśli tabele źródłowe i docelowe znajdują się w tym samym wystąpieniu programu SQL Server, łatwiej i szybciej jest użyć instrukcji Języka Transact-SQL INSERT … SELECT do skopiowania danych.

using System.Data.SqlClient;

static class Program
{
    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 = {0}", 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 = {0}", countEnd);
                Console.WriteLine("{0} rows were added.", countEnd - countStart);
                Console.WriteLine("Press Enter to finish.");
                Console.ReadLine();
            }
        }
    }

    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;";
    }
}
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 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

Wykonywanie operacji kopiowania zbiorczego przy użyciu języka Transact-SQL i klasy poleceń

Poniższy przykład ilustruje sposób użycia ExecuteNonQuery metody do wykonania instrukcji BULK INSERT.

Uwaga

Ścieżka pliku dla źródła danych jest względna względem serwera. Proces serwera musi mieć dostęp do tej ścieżki, aby operacja kopiowania zbiorczego powiodła się.

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

Zobacz też