Compartilhar via


Operação únicas de cópia em massa

A abordagem mais simples para a execução de uma operação de cópia em massa do SQL Server é executar uma única operação em um banco de dados. Por padrão, uma operação de cópia em massa é executada como uma operação isolada: a operação de cópia ocorre de forma não transacionada, sem a oportunidade de disponibilizá-la de volta.

Observação

Se você precisar reverter toda ou parte da cópia em massa quando ocorrer um erro, poderá usar uma transação gerenciada SqlBulkCopy ou executar a operação de cópia em massa dentro de uma transação existente. SqlBulkCopy também funcionará com System.Transactions se a conexão for inscrita (implícita ou explicitamente) em uma transação de System.Transactions.

Para obter mais informações, confira Operações de cópia em massa e transação.

As etapas gerais para executar uma operação de cópia em massa são:

  1. Conectar-se ao servidor de origem e obter os dados a serem copiados. Os dados também podem vir de outras fontes, desde que possam ser recuperados de um objeto IDataReader ou DataTable.

  2. Conecte-se ao servidor de destino (a menos que você queira que SqlBulkCopy estabeleça uma conexão para você).

  3. Crie um objeto SqlBulkCopy, configurando as propriedades necessárias.

  4. Defina a propriedade DestinationTableName para indicar a tabela de destino para a operação BULK INSERT.

  5. Chame um dos métodos WriteToServer.

  6. Opcionalmente, atualize as propriedades e chame WriteToServer novamente, conforme necessário.

  7. Chame Close ou encapsule as operações de cópia em massa em uma instrução Using.

Cuidado

É recomendável que os tipos de dados da coluna de origem e destino correspondam. Se os tipos de dados não corresponderem, o SqlBulkCopy tentará converter cada valor de origem para o tipo de dados de destino usando as regras empregadas por Value. As conversões podem afetar o desempenho e também podem resultar em erros inesperados. Por exemplo, um tipo de dados Double pode ser convertido em um tipo de dados Decimal na maior parte das vezes, mas não sempre.

Exemplo

O aplicativo de console a seguir demonstra como carregar dados usando a classe SqlBulkCopy. Neste exemplo, um SqlDataReader é usado para copiar dados da tabela Production.Product no banco de dados AdventureWorks do SQL Server em uma tabela semelhante no mesmo banco de dados.

Importante

Essa amostra não será executada, a menos que você tenha criado as tabelas de trabalho conforme descrito em Configuração de exemplo de cópia em massa. Esse código é fornecido para demonstrar a sintaxe para usar somente SqlBulkCopy. Se as tabelas de origem e destino estiverem localizadas na mesma instância do SQL Server, será mais fácil e mais rápido usar uma instrução INSERT … SELECT do Transact-SQL para copiar os dados.

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();
        }
    }
}
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
        Throw New NotImplementedException()
    End Function
End Module

Como executar uma operação de cópia em massa usando Transact-SQL e a classe command

O exemplo a seguir ilustra como usar o método ExecuteNonQuery para executar a instrução BULK INSERT.

Observação

O caminho do arquivo da fonte de dados é relativo ao servidor. O processo do servidor deve ter acesso a esse caminho para que a operação de cópia em massa seja bem-sucedida.

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

Confira também