Uso de la copia masiva con el controlador JDBCUsing bulk copy with the JDBC driver

DescargarDescargar controlador para JDBCDownloadDownload JDBC Driver

Microsoft SQL Server incluye una conocida utilidad de línea de comandos denominada bcp para copiar rápidamente y de forma masiva archivos grandes en tablas o vistas en bases de datos de SQL Server.Microsoft SQL Server includes a popular command-line utility named bcp for quickly bulk copying large files into tables or views in SQL Server databases. La clase SQLServerBulkCopy permite escribir soluciones de código en Java que proporcionan funciones similares.The SQLServerBulkCopy class allows you to write code solutions in Java that provide similar functionality. Hay otras maneras de cargar datos en una tabla de SQL Server (las instrucciones INSERT, por ejemplo) pero SQLServerBulkCopy ofrece una importante ventaja de rendimiento sobre ellas.There are other ways to load data into a SQL Server table (INSERT statements, for example) but SQLServerBulkCopy offers a significant performance advantage over them.

La clase SQLServerBulkCopy puede usarse para escribir datos solo en tablas de SQL Server.The SQLServerBulkCopy class can be used to write data only to SQL Server tables. Pero el origen de datos no se limita a SQL Server; se puede usar cualquiera, siempre y cuando los datos se puedan leer con una implementación de ResultSet, RowSet o ISQLServerBulkRecord.But the data source isn't limited to SQL Server; any data source can be used, as long as the data can be read with a ResultSet, RowSet, or ISQLServerBulkRecord implementation.

Con la clase SQLServerBulkCopy, puede ejecutar:Using the SQLServerBulkCopy class, you can perform:

  • Una única operación de copia masiva.A single bulk copy operation

  • Varias operaciones de copia masiva.Multiple bulk copy operations

  • Una operación de copia masiva con una transacciónA bulk copy operation with a transaction

Nota

Cuando se usa el Microsoft JDBC Driver 4.1 para SQL Server o versiones anteriores (que no admite la clase SQLServerBulkCopy), puede ejecutar la instrucción BULK INSERT de SQL Server Transact-SQL en su lugar.When using the Microsoft JDBC Driver 4.1 for SQL Server or earlier (which does not support the SQLServerBulkCopy class), you can execute the SQL Server Transact-SQL BULK INSERT statement instead.

Configuración de ejemplo de copia masivaBulk copy example setup

La clase SQLServerBulkCopy puede usarse para escribir datos solo en tablas de SQL Server.The SQLServerBulkCopy class can be used to write data only to SQL Server tables. En los ejemplos de código de este artículo se usa la base de datos de ejemplo de SQL Server AdventureWorks.The code samples shown in this article use the SQL Server sample database, AdventureWorks. Para evitar modificar los ejemplos de código de las tablas existentes, escriba los datos en tablas que debe crear antes.To avoid altering the existing tables in the code samples, write data to tables that you create first.

Las tablas BulkCopyDemoMatchingColumns y BulkCopyDemoDifferentColumns se basan en la tabla Production.Products de AdventureWorks.The BulkCopyDemoMatchingColumns and BulkCopyDemoDifferentColumns tables are both based on the AdventureWorks Production.Products table. En los ejemplos de código que usan estas tablas, los datos se agregan desde la tabla Production.Products a una de estas tablas de muestra.In code samples that use these tables, data is added from the Production.Products table to one of these sample tables. La tabla BulkCopyDemoDifferentColumns se usa cuando en el ejemplo se muestra cómo asignar columnas de los datos de origen a la tabla de destino; BulkCopyDemoMatchingColumns se usa para la mayoría de los ejemplos restantes.The BulkCopyDemoDifferentColumns table is used when the sample illustrates how to map columns from the source data to the destination table; BulkCopyDemoMatchingColumns is used for most other samples.

Algunos de los ejemplos de código muestran cómo usar una clase SQLServerBulkCopy para escribir en varias tablas.A few of the code samples demonstrate how to use one SQLServerBulkCopy class to write to multiple tables. En estos ejemplos, BulkCopyDemoOrderHeader y BulkCopyDemoOrderDetail se usan como tablas de destino.For these samples, the BulkCopyDemoOrderHeader and BulkCopyDemoOrderDetail tables are used as the destination tables. Estas tablas se basan en las tablas Sales.SalesOrderHeader y Sales.SalesOrderDetail de AdventureWorks.These tables are based on the Sales.SalesOrderHeader and Sales.SalesOrderDetail tables in AdventureWorks.

Nota

Los ejemplos de código SQLServerBulkCopy se proporcionan únicamente para mostrar la sintaxis para usar SQLServerBulkCopy.The SQLServerBulkCopy code samples are provided to demonstrate the syntax for using SQLServerBulkCopy only. Si las tablas de origen y destino se encuentran en la misma instancia de SQL Server, es más fácil y rápido usar una instrucción Transact-SQL INSERT... Instrucción SELECT para copiar los datos.If the source and destination tables are located in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT ... SELECT statement to copy the data.

Configuración de tablaTable setup

Para crear las tablas necesarias para que los ejemplos de código se ejecuten correctamente, debe ejecutar las siguientes instrucciones de Transact-SQL en una base de datos de SQL Server.To create the tables necessary for the code samples to run correctly, you must run the following Transact-SQL statements in a SQL Server database.

USE AdventureWorks  
  
IF EXISTS (SELECT * FROM dbo.sysobjects
 WHERE id = object_id(N'[dbo].[BulkCopyDemoMatchingColumns]')
 AND OBJECTPROPERTY(id, N'IsUserTable') = 1)  
    DROP TABLE [dbo].[BulkCopyDemoMatchingColumns]  
  
CREATE TABLE [dbo].[BulkCopyDemoMatchingColumns]([ProductID] [int] IDENTITY(1,1) NOT NULL,  
    [Name] [nvarchar](50) NOT NULL,  
    [ProductNumber] [nvarchar](25) NOT NULL,  
 CONSTRAINT [PK_ProductID] PRIMARY KEY CLUSTERED
(  
    [ProductID] ASC  
) ON [PRIMARY]) ON [PRIMARY]  
  
IF EXISTS (SELECT * FROM dbo.sysobjects
 WHERE id = object_id(N'[dbo].[BulkCopyDemoDifferentColumns]')
 AND OBJECTPROPERTY(id, N'IsUserTable') = 1)  
    DROP TABLE [dbo].[BulkCopyDemoDifferentColumns]  
  
CREATE TABLE [dbo].[BulkCopyDemoDifferentColumns]([ProdID] [int] IDENTITY(1,1) NOT NULL,  
    [ProdNum] [nvarchar](25) NOT NULL,  
    [ProdName] [nvarchar](50) NOT NULL,  
 CONSTRAINT [PK_ProdID] PRIMARY KEY CLUSTERED
(  
    [ProdID] ASC  
) ON [PRIMARY]) ON [PRIMARY]  
  
IF EXISTS (SELECT * FROM dbo.sysobjects
 WHERE id = object_id(N'[dbo].[BulkCopyDemoOrderHeader]')
 AND OBJECTPROPERTY(id, N'IsUserTable') = 1)  
    DROP TABLE [dbo].[BulkCopyDemoOrderHeader]  
  
CREATE TABLE [dbo].[BulkCopyDemoOrderHeader]([SalesOrderID] [int] IDENTITY(1,1) NOT NULL,  
    [OrderDate] [datetime] NOT NULL,  
    [AccountNumber] [nvarchar](15) NULL,  
 CONSTRAINT [PK_SalesOrderID] PRIMARY KEY CLUSTERED
(  
    [SalesOrderID] ASC  
) ON [PRIMARY]) ON [PRIMARY]  
  
IF EXISTS (SELECT * FROM dbo.sysobjects
 WHERE id = object_id(N'[dbo].[BulkCopyDemoOrderDetail]')
 AND OBJECTPROPERTY(id, N'IsUserTable') = 1)  
    DROP TABLE [dbo].[BulkCopyDemoOrderDetail]  
  
CREATE TABLE [dbo].[BulkCopyDemoOrderDetail]([SalesOrderID] [int] NOT NULL,  
    [SalesOrderDetailID] [int] NOT NULL,  
    [OrderQty] [smallint] NOT NULL,  
    [ProductID] [int] NOT NULL,  
    [UnitPrice] [money] NOT NULL,  
 CONSTRAINT [PK_LineNumber] PRIMARY KEY CLUSTERED
(  
    [SalesOrderID] ASC,  
    [SalesOrderDetailID] ASC  
) ON [PRIMARY]) ON [PRIMARY]  
  

Operaciones de copia masiva únicas.Single bulk copy operations

El método más sencillo para realizar una operación de copia masiva de SQL Server es realizar una operación única con una base de datos.The simplest approach to performing a SQL Server bulk copy operation is to perform a single operation against a database. De forma predeterminada, una operación de copia masiva se realiza como una operación aislada: la operación de copia tiene lugar sin transacciones y no es posible revertirla.By default, a bulk copy operation is performed as an isolated operation: the copy operation occurs in a non-transacted way, with no opportunity for rolling it back.

Nota

Si necesita revertir toda o parte de la copia masiva cuando se produce un error, puede usar una transacción administrada por SQLServerBulkCopy o realizar la operación de copia masiva en una transacción existente.If you need to roll back all or part of the bulk copy when an error occurs, you can either use a SQLServerBulkCopy-managed transaction, or perform the bulk copy operation within an existing transaction.
Para obtener más información, consulte Operaciones de transacción y de copia masivaFor more information, see Transaction and bulk copy operations

Los pasos generales para realizar una operación de copia masiva son:The general steps to perform a bulk copy operation are:

  1. Conéctese al servidor de origen y obtenga los datos que se van a copiar.Connect to the source server and obtain the data to be copied. Los datos también pueden provenir de otros orígenes, si se pueden recuperar de un objeto ResultSet o una implementación de ISQLServerBulkRecord.Data can also come from other sources, if it can be retrieved from a ResultSet object or an ISQLServerBulkRecord implementation.

  2. Conéctese al servidor de destino (a menos que quiera que SQLServerBulkCopy establezca una conexión automáticamente).Connect to the destination server (unless you want SQLServerBulkCopy to establish a connection for you).

  3. Cree un objeto SQLServerBulkCopy y establezca las propiedades necesarias a través de setBulkCopyOptions.Create a SQLServerBulkCopy object, setting any necessary properties via setBulkCopyOptions.

  4. Llame al método setDestinationTableName para indicar la tabla de destino para la operación de inserción masiva.Call the setDestinationTableName method to indicate the target table for the bulk insert operation.

  5. Llame a uno de los métodos writeToServer.Call one of the writeToServer methods.

  6. Opcionalmente, actualice las propiedades mediante setBulkCopyOptions y vuelva a llamar a writeToServer si fuese necesario.Optionally, update properties via setBulkCopyOptions and call writeToServer again as necessary.

  7. Llame a close, o bien encapsule las operaciones de copia masiva en una instrucción try con recursos.Call close, or wrap the bulk copy operations within a try-with-resources statement.

Precaución

Se recomienda que los tipos de datos de la columna de origen y de destino coincidan.We recommend that the source and target column data types match. Si los tipos de datos no coinciden, SQLServerBulkCopy intenta convertir los valores de origen al tipo de datos de destino.If the data types do not match, SQLServerBulkCopy attempts to convert each source value to the target data type. Las conversiones pueden afectar al rendimiento y también pueden producir errores inesperados.Conversions can affect performance, and also can result in unexpected errors. Por ejemplo, un tipo de datos double puede convertirse a un tipo de datos decimal la mayoría de las veces, pero no siempre.For example, a double data type can be converted to a decimal data type most of the time, but not always.

EjemploExample

En la aplicación siguiente se muestra cómo cargar datos mediante la clase SQLServerBulkCopy.The following application demonstrates how to load data using the SQLServerBulkCopy class. En este ejemplo se usa ResultSet para copiar datos de la tabla Production.Product de la base de datos AdventureWorks de SQL Server en una tabla similar de la misma base de datos.In this example, a ResultSet is used to copy data from the Production.Product table in the SQL Server AdventureWorks database to a similar table in the same database.

Importante

Este ejemplo no se ejecutará a menos que haya creado las tablas de trabajo como se describe en Configuración de tabla.This sample will not run unless you have created the work tables as described in Table setup. Este código se proporciona a fin de ilustrar únicamente la sintaxis para usar SQLServerBulkCopy.This code is provided to demonstrate the syntax for using SQLServerBulkCopy only. Si las tablas de origen y destino se encuentran en la misma instancia de SQL Server, es más fácil y rápido usar una instrucción Transact-SQL INSERT... Instrucción SELECT para copiar los datos.If the source and destination tables are located in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT ... SELECT statement to copy the data.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerBulkCopy;

public class BulkCopySingle {
    public static void main(String[] args) {
        String connectionUrl = "jdbc:sqlserver://<server>:<port>;databaseName=AdventureWorks;user=<user>;password=<password>";
        String destinationTable = "dbo.BulkCopyDemoMatchingColumns";
        int countBefore, countAfter;
        ResultSet rsSourceData;

        try (Connection sourceConnection = DriverManager.getConnection(connectionUrl);
                Connection destinationConnection = DriverManager.getConnection(connectionUrl);
                Statement stmt = sourceConnection.createStatement();
                SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(destinationConnection)) {

            // Empty the destination table.
            stmt.executeUpdate("DELETE FROM " + destinationTable);

            // Perform an initial count on the destination table.
            countBefore = getRowCount(stmt, destinationTable);

            // Get data from the source table as a ResultSet.
            rsSourceData = stmt.executeQuery("SELECT ProductID, Name, ProductNumber FROM Production.Product");

            // In real world applications you would
            // not use SQLServerBulkCopy to move data from one table to the other
            // in the same database. This is for demonstration purposes only.

            // Set up the bulk copy object.
            // Note that the column positions in the source
            // table match the column positions in
            // the destination table so there is no need to
            // map columns.
            bulkCopy.setDestinationTableName(destinationTable);

            // Write from the source to the destination.
            bulkCopy.writeToServer(rsSourceData);

            // Perform a final count on the destination
            // table to see how many rows were added.
            countAfter = getRowCount(stmt, destinationTable);
            System.out.println((countAfter - countBefore) + " rows were added.");
        }
        // Handle any errors that may have occurred.
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static int getRowCount(Statement stmt,
            String tableName) throws SQLException {
        ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + tableName);
        rs.next();
        int count = rs.getInt(1);
        rs.close();
        return count;
    }
}

Realizar una operación de copia masiva mediante Transact-SQLPerforming a bulk copy operation using Transact-SQL

En el ejemplo siguiente se muestra cómo usar el método executeUpdate para ejecutar la instrucción BULK INSERT.The following example illustrates how to use the executeUpdate method to execute the BULK INSERT statement.

Nota

La ruta de acceso al origen de datos depende del servidor.The file path for the data source is relative to the server. El proceso del servidor debe tener acceso a esa ruta para que la operación de copia masiva se realice correctamente.The server process must have access to that path in order for the bulk copy operation to succeed.

try (Connection con = DriverManager.getConnection(connectionUrl);
        Statement stmt = con.createStatement()) {
    // Perform the BULK INSERT
    stmt.executeUpdate(
            "BULK INSERT Northwind.dbo.[Order Details] " + "FROM 'f:\\mydata\\data.tbl' " + "WITH ( FORMATFILE='f:\\mydata\\data.fmt' )");
}

Varias operaciones de copia masiva.Multiple bulk copy operations

Puede realizar varias operaciones de copia masiva con una única instancia de una clase SQLServerBulkCopy.You can perform multiple bulk copy operations using a single instance of a SQLServerBulkCopy class. Si los parámetros de operación cambian entre copias (por ejemplo, el nombre de la tabla de destino), debe actualizarlos antes de las siguientes llamadas a cualquiera de los métodos writeToServer, como se muestra en el ejemplo siguiente.If the operation parameters change between copies (for example, the name of the destination table), you must update them prior to any subsequent calls to any of the writeToServer methods, as demonstrated in the following example. A menos que se cambien explícitamente, todos los valores de propiedad permanecen igual que estaban en la operación de copia masiva anterior para una instancia determinada.Unless explicitly changed, all property values remain the same as they were on the previous bulk copy operation for a given instance.

Nota

Generalmente, es más eficaz realizar varias operaciones de copia masiva con la misma instancia de SQLServerBulkCopy que usar una instancia independiente para cada operación.Performing multiple bulk copy operations using the same instance of SQLServerBulkCopy is usually more efficient than using a separate instance for each operation.

Si se realizan varias operaciones de copia masiva con el mismo objeto SQLServerBulkCopy, no hay restricciones en cuanto a si la información de origen o destino es igual o diferente en cada operación.If you perform several bulk copy operations using the same SQLServerBulkCopy object, there are no restrictions on whether source or target information is equal or different in each operation. Sin embargo, debe asegurarse de que la información de asociación de la columna está establecida correctamente cada vez que se escribe en el servidor.However, you must ensure that column association information is properly set each time you write to the server.

Importante

Este ejemplo no se ejecutará a menos que haya creado las tablas de trabajo como se describe en Configuración de tabla.This sample will not run unless you have created the work tables as described in Table setup. Este código se proporciona a fin de ilustrar únicamente la sintaxis para usar SQLServerBulkCopy.This code is provided to demonstrate the syntax for using SQLServerBulkCopy only. Si las tablas de origen y destino se encuentran en la misma instancia de SQL Server, es más fácil y rápido usar una instrucción Transact-SQL INSERT... Instrucción SELECT para copiar los datos.If the source and destination tables are located in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT ... SELECT statement to copy the data.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerBulkCopy;
import com.microsoft.sqlserver.jdbc.SQLServerBulkCopyOptions;

public class BulkCopyMultiple {
    public static void main(String[] args) {
        String connectionUrl = "jdbc:sqlserver://<server>:<port>;databaseName=AdventureWorks;user=<user>;password=<password>";
        String destinationHeaderTable = "dbo.BulkCopyDemoOrderHeader";
        String destinationDetailTable = "dbo.BulkCopyDemoOrderDetail";
        int countHeaderBefore, countDetailBefore, countHeaderAfter, countDetailAfter;
        ResultSet rsHeader, rsDetail;

        try (Connection sourceConnection1 = DriverManager.getConnection(connectionUrl);
                Connection sourceConnection2 = DriverManager.getConnection(connectionUrl);
                Statement stmt = sourceConnection1.createStatement();
                PreparedStatement preparedStmt1 = sourceConnection1.prepareStatement(
                        "SELECT [SalesOrderID], [OrderDate], [AccountNumber] FROM [Sales].[SalesOrderHeader] WHERE [AccountNumber] = ?;");
                PreparedStatement preparedStmt2 = sourceConnection2.prepareStatement(
                        "SELECT [Sales].[SalesOrderDetail].[SalesOrderID], [SalesOrderDetailID], [OrderQty], [ProductID], [UnitPrice] FROM "
                                + "[Sales].[SalesOrderDetail] INNER JOIN [Sales].[SalesOrderHeader] ON "
                                + "[Sales].[SalesOrderDetail].[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID] WHERE [AccountNumber] = ?;");
                SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(connectionUrl);) {

            // Empty the destination tables.
            stmt.executeUpdate("DELETE FROM " + destinationHeaderTable);
            stmt.executeUpdate("DELETE FROM " + destinationDetailTable);

            // Perform an initial count on the destination
            // table with matching columns.
            countHeaderBefore = getRowCount(stmt, destinationHeaderTable);

            // Perform an initial count on the destination
            // table with different column positions.
            countDetailBefore = getRowCount(stmt, destinationDetailTable);

            // Get data from the source table as a ResultSet.
            // The Sales.SalesOrderHeader and Sales.SalesOrderDetail
            // tables are quite large and could easily cause a timeout
            // if all data from the tables is added to the destination.
            // To keep the example simple and quick, a parameter is
            // used to select only orders for a particular account
            // as the source for the bulk insert.
            preparedStmt1.setString(1, "10-4020-000034");
            rsHeader = preparedStmt1.executeQuery();

            // Get the Detail data in a separate connection.
            preparedStmt2.setString(1, "10-4020-000034");
            rsDetail = preparedStmt2.executeQuery();

            // Create the SQLServerBulkCopySQLServerBulkCopy object.
            SQLServerBulkCopyOptions copyOptions = new SQLServerBulkCopyOptions();
            copyOptions.setBulkCopyTimeout(100);
            bulkCopy.setBulkCopyOptions(copyOptions);
            bulkCopy.setDestinationTableName(destinationHeaderTable);

            // Guarantee that columns are mapped correctly by
            // defining the column mappings for the order.
            bulkCopy.addColumnMapping("SalesOrderID", "SalesOrderID");
            bulkCopy.addColumnMapping("OrderDate", "OrderDate");
            bulkCopy.addColumnMapping("AccountNumber", "AccountNumber");

            // Write rsHeader to the destination.
            bulkCopy.writeToServer(rsHeader);

            // Set up the order details destination.
            bulkCopy.setDestinationTableName(destinationDetailTable);

            // Clear the existing column mappings
            bulkCopy.clearColumnMappings();

            // Add order detail column mappings.
            bulkCopy.addColumnMapping("SalesOrderID", "SalesOrderID");
            bulkCopy.addColumnMapping("SalesOrderDetailID", "SalesOrderDetailID");
            bulkCopy.addColumnMapping("OrderQty", "OrderQty");
            bulkCopy.addColumnMapping("ProductID", "ProductID");
            bulkCopy.addColumnMapping("UnitPrice", "UnitPrice");

            // Write rsDetail to the destination.
            bulkCopy.writeToServer(rsDetail);

            // Perform a final count on the destination
            // tables to see how many rows were added.
            countHeaderAfter = getRowCount(stmt, destinationHeaderTable);
            countDetailAfter = getRowCount(stmt, destinationDetailTable);

            System.out.println((countHeaderAfter - countHeaderBefore) + " rows were added to the Header table.");
            System.out.println((countDetailAfter - countDetailBefore) + " rows were added to the Detail table.");
        }
        // Handle any errors that may have occurred.
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static int getRowCount(Statement stmt,
            String tableName) throws SQLException {
        ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + tableName);
        rs.next();
        int count = rs.getInt(1);
        rs.close();
        return count;
    }
}

Operaciones de transacción y de copia masivaTransaction and bulk copy operations

Las operaciones de copia masiva se pueden realizar como operaciones aisladas o como parte de una transacción en varios pasos.Bulk copy operations can be performed as isolated operations or as part of a multiple step transaction. Esta última opción permite realizar más de una operación de copia masiva en la misma transacción, así como realizar otras operaciones de base de datos (como inserciones, actualizaciones y eliminaciones) mientras todavía se puede confirmar o revertir la transacción entera.This latter option enables you to perform more than one bulk copy operation within the same transaction, as well as perform other database operations (such as inserts, updates, and deletes) while still being able to commit or roll back the entire transaction.

De forma predeterminada, una operación de copia masiva se realiza como una operación aislada.By default, a bulk copy operation is performed as an isolated operation. La operación de copia masiva tiene lugar sin transacciones y sin la oportunidad de revertirla.The bulk copy operation occurs in a non-transacted way, with no opportunity for rolling it back. Si tiene que revertir toda o parte de la copia masiva cuando se produce un error, puede usar una transacción administrada por SQLServerBulkCopy, o bien realizar la operación de copia masiva dentro de una transacción existente.If you need to roll back all or part of the bulk copy when an error occurs, you can use a SQLServerBulkCopy-managed transaction or perform the bulk copy operation within an existing transaction.

Copia masiva extendida para Almacenamiento de datos de AzureExtended Bulk Copy for Azure Data Warehouse

La versión 8.4.1 del controlador agrega una nueva propiedad de conexión, sendTemporalDataTypesAsStringForBulkCopy.Driver version v8.4.1 adds a new connection property, sendTemporalDataTypesAsStringForBulkCopy. Esta propiedad booleana es true de manera predeterminada.This boolean property is true by default.

Esta propiedad de conexión, al establecerse en false, enviará los tipos de datos DATE, DATETIME, DATIMETIME2, DATETIMEOFFSET, SMALLDATETIME y TIME como sus tipos correspondientes en lugar de enviarlos como String.This connection property, when set to false, will send DATE, DATETIME, DATIMETIME2, DATETIMEOFFSET, SMALLDATETIME, and TIME datatypes as their respective types instead of sending them as String.

El envío de los tipos de datos temporales como sus tipos correspondientes permite al usuario enviar datos a esas columnas para Azure Synapse Analytics, lo que no era posible antes debido a la conversión por parte del controlador de los datos en String.Sending the temporal datatypes as their respective types allows the user to send data into those columns for Azure Synapse Analytics, which was not possible before due to the driver converting the data into String. El envío de datos String a columnas temporales funciona para SQL Server porque SQL Server realizaría la conversión implícita para nosotros, pero no es lo mismo con Azure Synapse Analytics.Sending String data into temporal columns works for SQL Server because SQL Server would perform implicit conversion for us, but it is not the same with Azure Synapse Analytics.

Además, incluso sin establecer esta cadena de conexión en "false", de v8.4.1 en adelante, los tipos de datos MONEY y SMALLMONEY se enviarán como tipos de datos MONEY / SMALLMONEY en lugar de DECIMAL, que también permite la copia masiva de esos tipos de datos en Azure Synapse Analytics.Additionally, even without setting this connection string to 'false', from v8.4.1 and onward, MONEY and SMALLMONEY datatypes will be sent as MONEY / SMALLMONEY datatypes instead of DECIMAL, which also allows those datatypes to be bulk copied into Azure Synapse Analytics.

Limitaciones de la copia masiva extendida para Almacenamiento de datos de AzureExtended Bulk Copy for Azure Data Warehouse limitations

Actualmente hay dos limitaciones:There are currently two limitations:

  1. Con esta propiedad de conexión establecida en false, el controlador solo aceptará el formato literal de cadena predeterminado de cada tipo de datos temporal, por ejemplo:With this connection property set to false, the driver will only accept the default string literal format of each temporal datatype, for example:

    DATE: YYYY-MM-DD

    DATETIME: YYYY-MM-DD hh:mm:ss[.nnn]

    DATETIME2: YYYY-MM-DD hh:mm:ss[.nnnnnnn]

    DATETIMEOFFSET: YYYY-MM-DD hh:mm:ss[.nnnnnnn] [{+/-}hh:mm]

    SMALLDATETIME:YYYY-MM-DD hh:mm:ss

    TIME: hh:mm:ss[.nnnnnnn]

  2. Con esta propiedad de conexión establecida en false, el tipo de columna especificado para la copia masiva debe respetar el gráfico de asignación de tipos de datos desde aquí.With this connection property set to false, the column type specified for bulk copy has to respect the data type mapping chart from here. Por ejemplo, anteriormente, los usuarios podían especificar java.sql.Types.TIMESTAMP para copiar datos de forma masiva en una columna DATE, pero con esta característica habilitada, deben especificar java.sql.Types.DATE para realizar la misma operación.For example, previously users could specify java.sql.Types.TIMESTAMP to bulk copy data into a DATE column, but with this feature enabled, they must specify java.sql.Types.DATE to perform the same.

Realizar una operación de copia masiva sin transaccionesPerforming a non-transacted bulk copy operation

La aplicación siguiente muestra lo que sucede cuando una operación de copia masiva sin transacciones encuentra un error en medio de la operación.The following application shows what happens when a non-transacted bulk copy operation encounters an error partway through the operation.

En el ejemplo, la tabla de origen y la de destino incluyen, cada una, una columna de identidad denominada ProductID.In the example, the source table and destination table each include an Identity column named ProductID. En primer lugar, el código prepara la tabla de destino mediante la eliminación de todas las filas y luego inserta una sola fila cuyo ProductID se sabe que existe en la tabla de origen.The code first prepares the destination table by deleting all rows and then inserting a single row whose ProductID is known to exist in the source table. De forma predeterminada, se genera un nuevo valor para la columna de identidad en la tabla de destino para cada fila agregada.By default, a new value for the Identity column is generated in the destination table for each row added. En este ejemplo, cuando se abre la conexión se establece una opción que obliga al proceso de carga masiva a usar los valores de identidad de la tabla de origen en su lugar.In this example, an option is set when the connection is opened that forces the bulk-load process to use the Identity values from the source table instead.

La operación de copia masiva se ejecuta con la propiedad BatchSize establecida en 10.The bulk copy operation is executed with the BatchSize property set to 10. Cuando la operación encuentra la fila no válida, se produce una excepción.When the operation encounters the invalid row, an exception is thrown. En este primer ejemplo, la operación de copia masiva es sin transacciones.In this first example, the bulk copy operation is non-transacted. Se confirman todos los lotes copiados hasta el punto del error; el lote que contiene la clave duplicada se revierte y la operación de copia masiva se detiene antes de procesar el resto de los lotes.All batches copied up to the point of the error are committed; the batch containing the duplicate key is rolled back, and the bulk copy operation is halted before processing any other batches.

Nota

Este ejemplo no se ejecutará a menos que haya creado las tablas de trabajo como se describe en Configuración de tabla.This sample will not run unless you have created the work tables as described in Table setup. Este código se proporciona a fin de ilustrar únicamente la sintaxis para usar SQLServerBulkCopy.This code is provided to demonstrate the syntax for using SQLServerBulkCopy only. Si las tablas de origen y destino se encuentran en la misma instancia de SQL Server, es más fácil y rápido usar una instrucción Transact-SQL INSERT... Instrucción SELECT para copiar los datos.If the source and destination tables are located in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT ... SELECT statement to copy the data.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerBulkCopy;
import com.microsoft.sqlserver.jdbc.SQLServerBulkCopyOptions;

public class BulkCopyNonTransacted {
    public static void main(String[] args) {
        String connectionUrl = "jdbc:sqlserver://<server>:<port>;databaseName=AdventureWorks;user=<user>;password=<password>";
        String destinationTable = "dbo.BulkCopyDemoMatchingColumns";
        int countBefore, countAfter;
        ResultSet rsSourceData;

        try (Connection sourceConnection = DriverManager.getConnection(connectionUrl);
                Statement stmt = sourceConnection.createStatement();
                SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(connectionUrl)) {

            // Empty the destination table.
            stmt.executeUpdate("DELETE FROM " + destinationTable);

            // Add a single row that will result in duplicate key
            // when all rows from source are bulk copied.
            // Note that this technique will only be successful in
            // illustrating the point if a row with ProductID = 446
            // exists in the AdventureWorks Production.Products table.
            // If you have made changes to the data in this table, change
            // the SQL statement in the code to add a ProductID that
            // does exist in your version of the Production.Products
            // table. Choose any ProductID in the middle of the table
            // (not first or last row) to best illustrate the result.
            stmt.executeUpdate("SET IDENTITY_INSERT " + destinationTable + " ON;" + "INSERT INTO " + destinationTable
                    + "([ProductID], [Name] ,[ProductNumber]) VALUES(446, 'Lock Nut 23','LN-3416'); SET IDENTITY_INSERT " + destinationTable
                    + " OFF");

            // Perform an initial count on the destination table.
            countBefore = getRowCount(stmt, destinationTable);

            // Get data from the source table as a ResultSet.
            rsSourceData = stmt.executeQuery("SELECT ProductID, Name, ProductNumber FROM Production.Product");

            // Set up the bulk copy object using the KeepIdentity option and BatchSize = 10.
            SQLServerBulkCopyOptions copyOptions = new SQLServerBulkCopyOptions();
            copyOptions.setKeepIdentity(true);
            copyOptions.setBatchSize(10);

            bulkCopy.setBulkCopyOptions(copyOptions);
            bulkCopy.setDestinationTableName(destinationTable);

            // Write from the source to the destination.
            // This should fail with a duplicate key error
            // after some of the batches have been copied.
            try {
                bulkCopy.writeToServer(rsSourceData);
            }
            catch (SQLException e) {
                e.printStackTrace();
            }

            // Perform a final count on the destination
            // table to see how many rows were added.
            countAfter = getRowCount(stmt, destinationTable);
            System.out.println((countAfter - countBefore) + " rows were added.");
        }
        // Handle any errors that may have occurred.
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static int getRowCount(Statement stmt,
            String tableName) throws SQLException {
        ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + tableName);
        rs.next();
        int count = rs.getInt(1);
        rs.close();
        return count;
    }
}

Realización de una operación de copia masiva dedicada en una transacciónPerforming a dedicated bulk copy operation in a transaction

De forma predeterminada, una operación de copia masiva no crea transacciones.By default, a bulk copy operation does not create transactions itself. Si quiere realizar una operación de copia masiva dedicada, cree una instancia de SQLServerBulkCopy con una cadena de conexión.When you want to perform a dedicated bulk copy operation, create a new instance of SQLServerBulkCopy with a connection string. En este escenario, la base de datos confirma de forma implícita cada lote de la operación de copia masiva.In this scenario, each batch of the bulk copy operation is implicitly committed by the database. Puede establecer la opción UseInternalTransaction en true en SQLServerBulkCopyOptions para hacer que la operación de copia masiva cree transacciones, y realizar una confirmación después de cada lote de la operación de copia masiva.You can set the UseInternalTransaction option to true in SQLServerBulkCopyOptions to make the bulk copy operation create transactions, performing a commit after each batch of the bulk copy operation.

SQLServerBulkCopyOptions copyOptions = new SQLServerBulkCopyOptions();
copyOptions.setKeepIdentity(true);
copyOptions.setBatchSize(10);
copyOptions.setUseInternalTransaction(true);

Uso de transacciones existentesUsing existing transactions

Puede pasar un objeto Connection con las transacciones habilitadas como un parámetro en un constructor de SQLServerBulkCopy.You can pass a Connection object that has transactions enabled as a parameter in a SQLServerBulkCopy constructor. En esta situación, la operación de copia masiva se realiza en una transacción existente y el estado de la transacción no sufre ningún cambio (es decir, ni se confirma ni se anula).In this situation, the bulk copy operation is performed in an existing transaction, and no change is made to the transaction state (that is, it's not committed or aborted). Esto permite que una aplicación incluya la operación de copia masiva en una transacción con otras operaciones de base de datos.This allows an application to include the bulk copy operation in a transaction with other database operations. Si se produce un error y tiene que revertir toda la operación de copia masiva, o bien si la copia masiva debe ejecutarse como parte de un proceso mayor que se pueda revertir, puede realizar la reversión en el objeto Connection en cualquier momento después de la operación de copia masiva.If you need to roll back the entire bulk copy operation because an error occurs, or if the bulk copy should execute as part of a larger process that can be rolled back, you can perform the rollback on the Connection object at any point after the bulk copy operation.

La aplicación siguiente es similar a BulkCopyNonTransacted, con una excepción: en este ejemplo, la operación de copia masiva se incluye en una transacción externa más grande.The following application is similar to BulkCopyNonTransacted, with one exception: in this example, the bulk copy operation is included in a larger, external transaction. Cuando se produce la infracción de la clave principal, toda la transacción se revierte y no se agrega ninguna fila a la tabla de destino.When the primary key violation error occurs, the entire transaction is rolled back and no rows are added to the destination table.

Nota

Este ejemplo no se ejecutará a menos que haya creado las tablas de trabajo como se describe en Configuración de tabla.This sample will not run unless you have created the work tables as described in Table setup. Este código se proporciona a fin de ilustrar únicamente la sintaxis para usar SQLServerBulkCopy.This code is provided to demonstrate the syntax for using SQLServerBulkCopy only. Si las tablas de origen y destino se encuentran en la misma instancia de SQL Server, es más fácil y rápido usar una instrucción Transact-SQL INSERT... Instrucción SELECT para copiar los datos.If the source and destination tables are located in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT ... SELECT statement to copy the data.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerBulkCopy;
import com.microsoft.sqlserver.jdbc.SQLServerBulkCopyOptions;

public class BulkCopyExistingTransactions {
    public static void main(String[] args) {
        String connectionUrl = "jdbc:sqlserver://<server>:<port>;databaseName=AdventureWorks;user=<user>;password=<password>";
        String destinationTable = "dbo.BulkCopyDemoMatchingColumns";
        int countBefore, countAfter;
        ResultSet rsSourceData;
        SQLServerBulkCopyOptions copyOptions;

        try (Connection sourceConnection = DriverManager.getConnection(connectionUrl);
                Connection destinationConnection = DriverManager.getConnection(connectionUrl);
                Statement stmt = sourceConnection.createStatement();
                SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(destinationConnection);) {

            // Empty the destination table.
            stmt.executeUpdate("DELETE FROM " + destinationTable);

            // Add a single row that will result in duplicate key
            // when all rows from source are bulk copied.
            // Note that this technique will only be successful in
            // illustrating the point if a row with ProductID = 446
            // exists in the AdventureWorks Production.Products table.
            // If you have made changes to the data in this table, change
            // the SQL statement in the code to add a ProductID that
            // does exist in your version of the Production.Products
            // table. Choose any ProductID in the middle of the table
            // (not first or last row) to best illustrate the result.
            stmt.executeUpdate("SET IDENTITY_INSERT " + destinationTable + " ON;" + "INSERT INTO " + destinationTable
                    + "([ProductID], [Name] ,[ProductNumber]) VALUES(446, 'Lock Nut 23','LN-3416'); SET IDENTITY_INSERT " + destinationTable
                    + " OFF");

            // Perform an initial count on the destination table.
            countBefore = getRowCount(stmt, destinationTable);

            // Get data from the source table as a ResultSet.
            rsSourceData = stmt.executeQuery("SELECT ProductID, Name, ProductNumber FROM Production.Product");

            // Set up the bulk copy object inside the transaction.
            destinationConnection.setAutoCommit(false);

            copyOptions = new SQLServerBulkCopyOptions();
            copyOptions.setKeepIdentity(true);
            copyOptions.setBatchSize(10);

            bulkCopy.setBulkCopyOptions(copyOptions);
            bulkCopy.setDestinationTableName(destinationTable);

            // Write from the source to the destination.
            // This should fail with a duplicate key error.
            try {
                bulkCopy.writeToServer(rsSourceData);
                destinationConnection.commit();
            }
            catch (SQLException e) {
                e.printStackTrace();
                destinationConnection.rollback();
            }

            // Perform a final count on the destination
            // table to see how many rows were added.
            countAfter = getRowCount(stmt, destinationTable);
            System.out.println((countAfter - countBefore) + " rows were added.");
        }
        catch (Exception e) {
            // Handle any errors that may have occurred.
            e.printStackTrace();
        }
    }

    private static int getRowCount(Statement stmt,
            String tableName) throws SQLException {
        ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + tableName);
        rs.next();
        int count = rs.getInt(1);
        rs.close();
        return count;
    }
}

Copia masiva desde un archivo CSVBulk copy from a CSV file

En la aplicación siguiente se muestra cómo cargar datos mediante la clase SQLServerBulkCopy.The following application demonstrates how to load data using the SQLServerBulkCopy class. En este ejemplo, se usa un archivo CSV para copiar datos exportados de la tabla Production.Product en la base de datos de AdventureWorks de SQL Server a una tabla similar en la base de datos.In this example, a CSV file is used to copy data exported from the Production.Product table in the SQL Server AdventureWorks database to a similar table in the database.

Importante

Este ejemplo no se ejecutará a menos que haya creado las tablas de trabajo como se describe en Configuración de tabla para obtenerlo.This sample will not run unless you have created the work tables as described in Table setup to get it.

  1. Abra SQL Server Management Studio y conéctese a SQL Server con la base de datos de AdventureWorks.Open SQL Server Management Studio and connect to the SQL Server with the AdventureWorks database.

  2. Expanda las bases de datos, haga clic con el botón derecho en la base de datos de AdventureWorks, seleccione Tareas y Exportar datos...Expand the databases, right-click the AdventureWorks database, select Tasks and Export Data...

  3. Para el origen de datos, seleccione el origen de datos que le permita conectarse a SQL Server (por ejemplo, SQL Server Native Client 11.0), compruebe la configuración y, después, seleccione Siguiente.For the Data Source, select the Data source that allows you to connect to your SQL Server (for example, SQL Server Native Client 11.0), check the configuration and then Next

  4. Para el destino, seleccione el Destino de archivo plano y escriba un Nombre de archivo con un destino como C:\Test\TestBulkCSVExample.csv.For the Destination, Select the Flat File Destination and enter a File Name with a destination such as C:\Test\TestBulkCSVExample.csv. Compruebe que el formato está delimitado, el calificador de texto es ninguno y habilite Nombres de columna en la primera fila de datos; después, haga clic en Siguiente.Check that the Format is Delimited, the Text qualifier is none, and enable Column names in the first data row, and then select Next

  5. Seleccione Escribir una consulta para especificar los datos que se van a transferir y haga clic en Siguiente.Select Write a query to specify the data to transfer and Next. Escriba la instrucción SQL SELECT ProductID, Name, ProductNumber FROM Production.Product y seleccione Siguiente.Enter your SQL Statement SELECT ProductID, Name, ProductNumber FROM Production.Product, and Next

  6. Comprobar la configuración: puede dejar el delimitador de filas como {CR}{LF} y el delimitador de columna como Coma {,}.Check the configuration: You can leave the Row delimiter as {CR}{LF} and Column Delimiter as Comma {,}. Seleccione Editar asignaciones y compruebe que el Tipo de datos es correcto para cada columna (por ejemplo, entero para ProductID y cadena Unicode para las demás).Select Edit Mappings... and check that the data Type is correct for each column (for example, integer for ProductID and Unicode string for the others).

  7. Vaya directamente a Finalizar y ejecute la exportación.Skip ahead to Finish and run the export.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.microsoft.sqlserver.jdbc.SQLServerBulkCSVFileRecord;
import com.microsoft.sqlserver.jdbc.SQLServerBulkCopy;

public class BulkCopyCSV {
    public static void main(String[] args) {
        String connectionUrl = "jdbc:sqlserver://<server>:<port>;databaseName=AdventureWorks;user=<user>;password=<password>";
        String destinationTable = "dbo.BulkCopyDemoMatchingColumns";
        int countBefore, countAfter;

        // Get data from the source file by loading it into a class that implements ISQLServerBulkRecord.
        // Here we are using the SQLServerBulkCSVFileRecord implementation to import the example CSV file.
        try (Connection destinationConnection = DriverManager.getConnection(connectionUrl);
                Statement stmt = destinationConnection.createStatement();
                SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(destinationConnection);
                SQLServerBulkCSVFileRecord fileRecord = new SQLServerBulkCSVFileRecord("C:\\Test\\TestBulkCSVExample.csv", true);) {

            // Set the metadata for each column to be copied.
            fileRecord.addColumnMetadata(1, null, java.sql.Types.INTEGER, 0, 0);
            fileRecord.addColumnMetadata(2, null, java.sql.Types.NVARCHAR, 50, 0);
            fileRecord.addColumnMetadata(3, null, java.sql.Types.NVARCHAR, 25, 0);

            // Empty the destination table.
            stmt.executeUpdate("DELETE FROM " + destinationTable);

            // Perform an initial count on the destination table.
            countBefore = getRowCount(stmt, destinationTable);

            // 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.
            bulkCopy.setDestinationTableName(destinationTable);

            // Write from the source to the destination.
            bulkCopy.writeToServer(fileRecord);

            // Perform a final count on the destination
            // table to see how many rows were added.
            countAfter = getRowCount(stmt, destinationTable);
            System.out.println((countAfter - countBefore) + " rows were added.");
        }
        // Handle any errors that may have occurred.
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static int getRowCount(Statement stmt,
            String tableName) throws SQLException {
        ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + tableName);
        rs.next();
        int count = rs.getInt(1);
        rs.close();
        return count;
    }
}

Copia masiva con delimitadores como datos en un archivo CSVBulk copy with delimiters as data in CSV file

La versión 8.4.1 del controlador agrega una nueva API SQLServerBulkCSVFileRecord.setEscapeColumnDelimitersCSV(boolean).Driver version 8.4.1 adds a new API SQLServerBulkCSVFileRecord.setEscapeColumnDelimitersCSV(boolean). Al establecerse en true, se aplicarán las siguientes reglas:When set to true, the following rules will apply:

  • Cada campo se puede incluir o no entre comillas dobles.Each field may or may not be enclosed in double quotes.
  • Si los campos no se incluyen entre comillas dobles, es posible que no aparezcan comillas dobles dentro de los campos.If fields are not enclosed with double quotes, then double quotes may not appear inside the fields.
  • Los campos que contienen comillas dobles y los delimitadores deben incluirse entre comillas dobles.Fields containing double quotes, and delimiters should be enclosed in double quotes.
  • Si se usan comillas dobles para incluir los campos, las comillas dobles que aparecen dentro de un campo deben tener caracteres de escape mediante la inclusión de otras comillas dobles delante.If double-quotes are used to enclose fields, then a double-quote appearing inside a field must be escaped by preceding it with another double quote.

Copia masiva con columnas Always EncryptedBulk copy with Always Encrypted columns

A partir de Microsoft JDBC Driver 6.0 para SQL Server, la copia masiva es compatible con las columnas Always Encrypted.Beginning with Microsoft JDBC Driver 6.0 for SQL Server, bulk copy is supported with Always Encrypted columns.

En función de las opciones de copia masiva y el tipo de cifrado de las tablas de origen y destino, el controlador JDBC puede descifrar los datos de forma transparente y después volver a cifrarlos, o bien puede enviar los datos cifrados tal como están.Depending on the bulk copy options, and the encryption type of the source and destination tables the JDBC driver may transparently decrypt and then encrypt the data or it may send the encrypted data as is. Por ejemplo, cuando se copian datos masivamente desde una columna cifrada a una columna sin cifrar, el controlador descifra de forma transparente los datos antes de enviarlos a SQL Server.For example, when bulk copying data from an encrypted column to an unencrypted column, the driver transparently decrypts data before sending to SQL Server. De igual forma, cuando se copian datos masivamente desde una columna sin cifrar (o desde un archivo .csv) a una columna cifrada, el controlador descifra de forma transparente los datos antes de enviarlos a SQL Server.Similarly when bulk copying data from an unencrypted column (or from a CSV file) to an encrypted column, the driver transparently encrypts data before sending to SQL Server. Si tanto el origen como el destino están cifrados, según la opción de copa masiva allowEncryptedValueModifications, el controlador enviaría los datos tal como están o los descifraría y los volvería a cifrar antes de enviarlos a SQL Server.If both source and destination is encrypted, then depending on the allowEncryptedValueModifications bulk copy option, the driver would send data as is or would decrypt the data and encrypt it again before sending to SQL Server.

Para obtener más información, vea la opción de copia masiva allowEncryptedValueModifications siguiente y Uso de Always Encrypted con el controlador JDBC.For more information, see the allowEncryptedValueModifications bulk copy option below, and Using Always Encrypted with the JDBC Driver.

Importante

Limitación de Microsoft JDBC Driver 6.0 para SQL Server, al copiar masivamente datos desde un archivo .csv a columnas cifradas:Limitation of the Microsoft JDBC Driver 6.0 for SQL Server, when bulk copying data from a CSV file to encrypted columns:

Solo el tipo de formato de literal de cadena predeterminado Transact-SQL es compatible con los tipos de fecha y horaOnly the Transact-SQL default string literal format is supported for the date and time types

No se admiten los tipos de datos DATETIME y SMALLDATETIMEDATETIME and SMALLDATETIME data types are not supported

API de copia masiva para el controlador JDBCBulk copy API for JDBC driver

SQLServerBulkCopySQLServerBulkCopy

Le permite la carga masiva de forma eficaz de una tabla de SQL Server con datos procedentes de otro origen.Lets you efficiently bulk-load a SQL Server table with data from another source.

Microsoft SQL Server incluye una conocida utilidad del símbolo del sistema denominada bcp para mover datos de una tabla a otra, ya sea en un único servidor o entre servidores.Microsoft SQL Server includes a popular command-prompt utility named bcp for moving data from one table to another, whether on a single server or between servers. La clase SQLServerBulkCopy le permite escribir soluciones de código en Java que proporcionan una funcionalidad similar.The SQLServerBulkCopy class lets you write code solutions in Java that provide similar functionality. Hay otras maneras de cargar datos en una tabla de SQL Server (las instrucciones INSERT, por ejemplo), pero SQLServerBulkCopy ofrece una importante ventaja de rendimiento sobre ellas.There are other ways to load data into a SQL Server table (INSERT statements, for example), but SQLServerBulkCopy offers a significant performance advantage over them.

La clase SQLServerBulkCopy puede usarse para escribir datos solo en tablas de SQL Server.The SQLServerBulkCopy class can be used to write data only to SQL Server tables. Pero el origen de datos no se limita a SQL Server; se puede usar cualquiera, siempre que los datos se puedan leer con una instancia de ResultSet o una implementación de ISQLServerBulkRecord.However, the data source isn't limited to SQL Server; any data source can be used, as long as the data can be read with a ResultSet instance or ISQLServerBulkRecord implementation.

ConstructorConstructor DescripciónDescription
SQLServerBulkCopy(Connection connection) Inicializa una instancia nueva de la clase SQLServerBulkCopy mediante la instancia abierta especificada de SQLServerConnection.Initializes a new instance of the SQLServerBulkCopy class using the specified open instance of SQLServerConnection. Si Connection tiene habilitadas las transacciones, las operaciones de copia se realizarán dentro de esa transacción.If the Connection has transactions enabled, the copy operations will be performed within that transaction.
SQLServerBulkCopy(String connectionURL) Inicializa y abre una instancia nueva de SQLServerConnection en función del valor connectionURL proporcionado.Initializes and opens a new instance of SQLServerConnection based on the supplied connectionURL. El constructor usa SQLServerConnection para inicializar una instancia nueva de la clase SQLServerBulkCopy.The constructor uses the SQLServerConnection to initialize a new instance of the SQLServerBulkCopy class.
PropiedadProperty DescripciónDescription
String DestinationTableName Nombre de la tabla de destino en el servidor.Name of the destination table on the server.

Si DestinationTableName no se ha establecido al llamar a writeToServer, se inicia una excepción SQLServerException.If DestinationTableName hasn't been set when writeToServer is called, a SQLServerException is thrown.

DestinationTableName es un nombre de tres partes (<database>.<owningschema>.<name>).DestinationTableName is a three-part name (<database>.<owningschema>.<name>). Si quiere, puede calificar el nombre de tabla con su base de datos y esquema propietario.You can qualify the table name with its database and owning schema if you choose. Sin embargo, si el nombre de tabla usa un carácter de subrayado ("") o cualquier otro carácter especial, el nombre ha de ir entre corchetes.However, if the table name uses an underscore ("") or any other special characters, you must escape the name using surrounding brackets. Para obtener más información, vea Database Identifiers.For more information, see Database Identifiers.
ColumnMappings Las asignaciones de columnas definen las relaciones entre las columnas del origen de datos y las columnas en el destino.Column mappings define the relationships between columns in the data source and columns in the destination.

Si no se definen las asignaciones, las columnas se asignan de forma implícita según la posición ordinal.If mappings aren't defined, the columns are mapped implicitly based on ordinal position. Para que esto funcione, los esquemas de origen y destino deben coincidir.For this to work, source and target schemas must match. Si no es así, se producirá una excepción.If they don't, an Exception will be thrown.

Si las asignaciones no están vacías, no hay que especificar todas las columnas presentes en el origen de datos.If the mappings isn't empty, not every column present in the data source has to be specified. Se ignoran aquellas que no estén asignadas.Those not mapped are ignored.

Puede hacer referencia a las columnas de origen y de destino tanto por nombre como por ordinal.You can refer to source and target columns by either name or ordinal.
MétodoMethod DescripciónDescription
void addColumnMapping(int sourceColumn, int destinationColumn) Agrega una nueva asignación de columnas, usando las posiciones ordinales para especificar tanto las columnas de origen como las de destino.Adds a new column-mapping, using ordinals to specify both source and destination columns.
void addColumnMapping (int sourceColumn, String destinationColumn) Agrega una nueva asignación de columnas, con un valor ordinal para la columna de origen y un nombre de columna para la columna de destino.Adds a new column-mapping, using an ordinal for the source column and a column name for the destination column.
void addColumnMapping (String sourceColumn, int destinationColumn) Agrega una nueva asignación de columnas, con un nombre de columna para describir la columna de origen y un valor ordinal para especificar la columna de destino.Adds a new column-mapping, using a column name to describe the source column and an ordinal to specify the destination column.
void addColumnMapping (String sourceColumn, String destinationColumn) Agrega una nueva asignación de columnas, usando los nombres de columna para especificar tanto las columnas de origen como las de destino.Adds a new column-mapping, using column names to specify both source and destination columns.
void clearColumnMappings() Elimina el contenido de las asignaciones de columnas.Clears the contents of the column mappings.
void close() Cierra la instancia de SQLServerBulkCopy.Closes the SQLServerBulkCopy instance.
SQLServerBulkCopyOptions getBulkCopyOptions() Recupera el conjunto actual de SQLServerBulkCopyOptions.Retrieves the current set of SQLServerBulkCopyOptions.
String getDestinationTableName() Recupera el nombre de tabla de destino actual.Retrieve the current destination table name.
void setBulkCopyOptions(SQLServerBulkCopyOptions copyOptions) Actualiza el comportamiento de la instancia de SQLServerBulkCopy según las opciones proporcionadas.Updates the behavior of the SQLServerBulkCopy instance according to the options supplied.
void setDestinationTableName(String tableName) Establece el nombre de la tabla de destino.Sets the name of the destination table.
void writeToServer(ResultSet sourceData) Copia todas las filas del objeto ResultSet proporcionado en una tabla de destino especificada por la propiedad DestinationTableName del objeto SQLServerBulkCopy.Copies all rows in the supplied ResultSet to a destination table specified by the DestinationTableName property of the SQLServerBulkCopy object.
void writeToServer(RowSet sourceData) Copia todas las filas del objeto RowSet proporcionado en una tabla de destino especificada por la propiedad DestinationTableName del objeto SQLServerBulkCopy.Copies all rows in the supplied RowSet to a destination table specified by the DestinationTableName property of the SQLServerBulkCopy object.
void writeToServer(ISQLServerBulkRecord sourceData) Copia todas las filas de la implementación de ISQLServerBulkRecord proporcionada en una tabla de destino especificada por la propiedad DestinationTableName del objeto SQLServerBulkCopy.Copies all rows in the supplied ISQLServerBulkRecord implementation to a destination table specified by the DestinationTableName property of the SQLServerBulkCopy object.

SQLServerBulkCopyOptionsSQLServerBulkCopyOptions

Una colección de valores que controlan cómo se comportan los métodos writeToServer en una instancia de SQLServerBulkCopy.A collection of settings that control how the writeToServer methods behave in an instance of SQLServerBulkCopy.

ConstructorConstructor DescripciónDescription
SQLServerBulkCopyOptions() Inicializa una instancia nueva de la clase SQLServerBulkCopyOptions con los valores predeterminados para todas las configuraciones.Initializes a new instance of the SQLServerBulkCopyOptions class using defaults for all of the settings.

Los captadores y establecedores están disponibles para las siguientes opciones:Getters and setters exist for the following options:

OpciónOption DescripciónDescription Valor predeterminadoDefault
boolean CheckConstraints Comprueba las restricciones mientras se insertan los datos.Check constraints while data is being inserted. False: no se comprueban las restriccionesFalse - constraints aren't checked
boolean FireTriggers Provoca que el servidor active los desencadenadores de inserción para las filas que se insertan en la base de datos.Cause the server to fire the insert triggers for the rows being inserted into the database. False: no se activa ningún desencadenadorFalse - no triggers are fired
boolean KeepIdentity Mantiene los valores de identidad de origen.Preserve source identity values. False: el destino asigna los valores de identidadFalse - identity values are assigned by the destination
boolean KeepNulls Conserva los valores nulos en la tabla de destino independientemente de la configuración para los valores predeterminados.Preserve null values in the destination table regardless of the settings for default values. False: los valores nulos se reemplazan por valores predeterminados si procedeFalse - null values are replaced by default values where applicable.
boolean TableLock Obtiene un bloqueo de actualización masiva durante toda la operación de copia masiva.Obtain a bulk update lock for the duration of the bulk copy operation. False: se usan bloqueos de fila.False - row locks are used.
boolean UseInternalTransaction Cuando se establece en true, cada lote de la operación de copia masiva tendrá lugar en una transacción.When set to true, each batch of the bulk-copy operation will occur within a transaction. Si SQLServerBulkCopy usa una conexión existente (como se especifica en el constructor), se iniciará una excepción SQLServerException.If SQLServerBulkCopy is using an existing connection (as specified by the constructor), a SQLServerException will occur. Si SQLServerBulkCopy ha creado una conexión dedicada, se creará y confirmará una transacción para cada lote.If SQLServerBulkCopy created a dedicated connection, a transaction will be created and committed for each batch. False: no hay ninguna transacciónFalse - no transaction
int BatchSize Número de filas en cada lote.Number of rows in each batch. Al final de cada lote, las filas del lote se envían al servidor.At the end of each batch, the rows in the batch are sent to the server.

Un lote estará completo cuando se hayan procesado las filas indicadas por BatchSize o no haya más filas para enviar al origen de datos de destino.A batch is complete when BatchSize rows have been processed or there are no more rows to send to the destination data source. Si la instancia de SQLServerBulkCopy se ha declarado con la opción UseInternalTransaction establecida en false, se envían al servidor BatchSize filas a la vez, pero no se realiza ninguna acción relacionada con la transacción.If the SQLServerBulkCopy instance has been declared with the UseInternalTransaction option set to false, rows are sent to the server BatchSize rows at a time, but no transaction-related action is taken. Si UseInternalTransaction se establece en true, cada lote de filas se realiza dentro de una transacción explícita.If UseInternalTransaction is set to true, each batch of rows is performed within an explicit transaction.
0: indica que cada operación writeToServer es un lote único0 - indicates that each writeToServer operation is a single batch
int BulkCopyTimeout Cantidad de segundos para que se complete la operación antes de que se agote el tiempo de espera. Un valor de 0 indica sin límite; la copia masiva esperará indefinidamente.Number of seconds for the operation to complete before it times out. A value of 0 indicates no limit; the bulk copy will wait indefinitely. 60 segundos.60 seconds.
boolean allowEncryptedValueModifications Esta opción está disponible con Microsoft JDBC Driver 6.0 (o superior) para SQL Server.This option is available with Microsoft JDBC Driver 6.0 (or higher) for SQL Server.

Cuando se establece en true, allowEncryptedValueModifications habilita la copia masiva de datos cifrados entre tablas o bases de datos, sin descifrarlos.When set to true, allowEncryptedValueModifications enables bulk copying of encrypted data between tables or databases, without decrypting the data. Normalmente, una aplicación seleccionaría datos de las columnas cifradas de una tabla sin descifrar los datos (la aplicación se conectaría a la base de datos con la palabra clave de configuración de cifrado de columnas establecida en deshabilitada) y después usaría esta opción para insertar masivamente los datos, que siguen estando cifrados.Typically, an application would select data from encrypted columns from one table without decrypting the data (the app would connect to the database with the column encryption setting keyword set to disabled) and then would use this option to bulk insert the data, which is still encrypted. Para obtener más información, vea Uso de Always Encrypted con JDBC Driver.For more information, see Using Always Encrypted with the JDBC Driver.

Tenga cuidado al establecer allowEncryptedValueModifications en true, ya que puede provocar daños en la base de datos porque el controlador no comprueba si los datos están realmente cifrados, o si se han cifrado correctamente mediante la misma clave, algoritmo y tipo de cifrado que la columna de destino.Use caution when setting allowEncryptedValueModifications to true as this may lead to corrupting the database because the driver doesn't check if the data is indeed encrypted, or if it is correctly encrypted using the same encryption type, algorithm and key as the target column.

Captadores y establecedores:Getters and setters:

MétodosMethods DescripciónDescription
boolean isCheckConstraints() Indica si las restricciones deben comprobarse mientras se insertan o no los datos.Indicates whether constraints are to be checked while data is being inserted or not.
void setCheckConstraints(boolean checkConstraints) Establece si las restricciones deben comprobarse mientras se insertan o no los datos.Sets whether constraints are to be checked while data is being inserted or not.
boolean isFireTriggers() Indica si el servidor debe activar los desencadenadores de inserción para las filas que se insertan en la base de datos.Indicates if the server should fire the insert triggers for the rows being inserted into the database.
void setFireTriggers(boolean fireTriggers) Establece si el servidor se debe configurar para activar los desencadenadores de inserción para las filas que se insertan en la base de datos.Sets whether the server should be set to fire triggers for the rows being inserted into the database.
boolean isKeepIdentity() Indica si se deben conservar o no los valores de identidad de origen.Indicates whether or not to preserve any source identity values.
void setKeepIdentity(boolean keepIdentity) Establece si se deben conservar o no los valores de identidad.Sets whether or not to preserve identity values.
boolean isKeepNulls() Indica si se deben conservar valores NULL en la tabla de destino independientemente de la configuración de los valores predeterminados, o bien si deben reemplazarse por los valores predeterminados (si procede).Indicates whether to preserve null values in the destination table regardless of the settings for default values, or if they should be replaced by the default values (where applicable).
void setKeepNulls(boolean keepNulls) Establece si se deben conservar valores NULL en la tabla de destino independientemente de la configuración de los valores predeterminados, o bien si deben reemplazarse por los valores predeterminados (si procede).Sets whether to preserve null values in the destination table regardless of the settings for default values, or if they should be replaced by the default values (where applicable).
boolean isTableLock() Indica si SQLServerBulkCopy debe obtener un bloqueo de actualización masiva durante toda la operación de copia masiva.Indicates whether SQLServerBulkCopy should obtain a bulk update lock for the duration of the bulk copy operation.
void setTableLock(boolean tableLock) Establece si SQLServerBulkCopy debe obtener un bloqueo de actualización masiva durante toda la operación de copia masiva.Sets whether SQLServerBulkCopy should obtain a bulk update lock for the duration of the bulk copy operation.
boolean isUseInternalTransaction() Indica si cada lote de la operación de copia masiva tendrá lugar en una transacción.Indicates whether each batch of the bulk-copy operation will occur within a transaction.
void setUseInternalTranscation(boolean useInternalTransaction) Establece si cada lote de las operaciones de copia masiva tendrá lugar en una transacción o no.Sets whether each batch of the bulk-copy operations will occur within a transaction or not.
int getBatchSize() Obtiene el número de filas en cada lote.Gets the number of rows in each batch. Al final de cada lote, las filas del lote se envían al servidor.At the end of each batch, the rows in the batch are sent to the server.
void setBatchSize(int batchSize) Establece el número de filas en cada lote.Sets the number of rows in each batch. Al final de cada lote, las filas del lote se envían al servidor.At the end of each batch, the rows in the batch are sent to the server.
int getBulkCopyTimeout() Obtiene la cantidad de segundos para que se complete la operación antes de que se agote el tiempo de espera.Gets the number of seconds for the operation to complete before it times out.
void setBulkCopyTimeout(int timeout) Establece la cantidad de segundos para que se complete la operación antes de que se agote el tiempo de espera.Sets the number of seconds for the operation to complete before it times out.
boolean isAllowEncryptedValueModifications() Indica si el valor allowEncryptedValueModifications está habilitado o deshabilitado.Indicates whether allowEncryptedValueModifications setting is enabled or disabled.
void setAllowEncryptedValueModifications(boolean allowEncryptedValueModifications) Configura la opción allowEncryptedValueModifications que se usa para la copia masiva con columnas Always Encrypted.Configures the allowEncryptedValueModifications setting that is used for bulk copy with Always Encrypted columns.

ISQLServerBulkRecordISQLServerBulkRecord

La interfaz ISQLServerBulkRecord se puede usar para crear las clases que leen datos de cualquier origen (como un archivo) y permitir que una instancia de SQLServerBulkCopy cargue de forma masiva una tabla de SQL Server con esos datos.The ISQLServerBulkRecord interface can be used to create classes that read in data from any source (such as a file) and allow a SQLServerBulkCopy instance to bulk load a SQL Server table with that data.

Métodos de interfazInterface Methods DescripciónDescription
set<Integer> getColumnOrdinals() Obtiene los ordinales para cada una de las columnas representadas en este registro de datos.Get the ordinals for each of the columns represented in this data record.
String getColumnName(int column) Obtiene el nombre de una columna determinada.Get the name of the given column.
int getColumnType(int column) Obtiene el tipo de datos JDBC de la columna especificada.Get the JDBC data type of the given column.
int getPrecision(int column) Obtiene la precisión de la columna especificada.Get the precision for the given column.
object[] getRowData() Obtiene los datos de la fila actual como una matriz de objetos.Gets the data for the current row as an array of Objects.

Cada objeto debe coincidir con el tipo de lenguaje Java que se usa para representar el tipo de datos JDBC indicado para la columna especificada.Each Object must match the Java language Type that is used to represent the indicated JDBC data type for the given column. Para obtener más información, vea Descripción de los tipos de datos del controlador JDBC para obtener las asignaciones adecuadas.For more information, see Understanding the JDBC Driver Data Types for the appropriate mappings.
int getScale(int column) Obtiene la escala de la columna especificada.Get the scale for the given column.
boolean isAutoIncrement(int column) Indica si la columna es representa una columna de identidad.Indicates whether the column represents an identity column.
boolean next() Avanza a la siguiente fila de datos.Advances to the next data row.

SQLServerBulkCSVFileRecordSQLServerBulkCSVFileRecord

Se puede usar una implementación sencilla de la interfaz ISQLServerBulkRecord para leer en los tipos de datos básicos de Java desde un archivo delimitado, donde cada línea representa una fila de datos.A simple implementation of the ISQLServerBulkRecord interface that can be used to read in the basic Java data types from a delimited file where each line represents a row of data.

Limitaciones y notas de implementación:Implementation Notes and Limitations:

  1. La cantidad máxima de datos permitida en una fila determinada está limitada por la memoria disponible, ya que los datos se leen en una línea cada vez.The maximum amount of data allowed in any given row is limited by the available memory because the data is read one line at a time.

  2. No se admite el streaming de tipos de datos de gran tamaño como varchar(max), varbinary(max), nvarchar(max), sqlxml y ntext.Streaming of large data types such as varchar(max), varbinary(max), nvarchar(max), sqlxml, and ntext isn't supported.

  3. El delimitador especificado para el archivo CSV no debe aparecer en ninguna parte de los datos y debe convertirse correctamente si es un carácter restringido en expresiones regulares de Java.The delimiter specified for the CSV file shouldn't appear anywhere in the data and should be escaped properly if it is a restricted character in Java regular expressions.

  4. En la implementación del archivo CSV, las comillas dobles se tratan como parte de los datos.In the CSV file implementation, double quotes are treated as part of the data. Por ejemplo, si el delimitador es una coma, la línea hello,"world","hello,world" se tratará como si tuviera cuatro columnas con los valores hello, "world", "hello y world".For example, the line hello,"world","hello,world" would be treated as having four columns with the values hello, "world", "hello and world" if the delimiter is a comma.

  5. Los caracteres de nueva línea se usan como terminadores de fila y no están permitidos en ninguna parte de los datos.New line characters are used as row terminators and aren't allowed anywhere in the data.

ConstructorConstructor DescripciónDescription
SQLServerBulkCSVFileRecord(String fileToParse, String encoding, String delimiter, boolean firstLineIsColumnNames) Inicializa una instancia nueva de la clase SQLServerBulkCSVFileRecord que analizará cada línea de fileToParse con el delimitador y la codificación proporcionados.Initializes a new instance of the SQLServerBulkCSVFileRecord class that will parse each line in the fileToParse with the provided delimiter and encoding. Si firstLineIsColumnNames se establece en True, la primera línea del archivo se analizará como nombres de columna.If firstLineIsColumnNames is set to True, the first line in the file will be parsed as column names. Si la codificación es NULL, se usará la codificación predeterminada.If encoding is NULL, the default encoding will be used.
SQLServerBulkCSVFileRecord(String fileToParse, String encoding, boolean firstLineIsColumnNames) Inicializa una instancia nueva de la clase SQLServerBulkCSVFileRecord que analizará cada línea de fileToParse con una coma como delimitador y la codificación proporcionada.Initializes a new instance of the SQLServerBulkCSVFileRecord class that will parse each line in the fileToParse with a comma as the delimiter and provided encoding. Si firstLineIsColumnNames se establece en True, la primera línea del archivo se analizará como nombres de columna.If firstLineIsColumnNames is set to True, the first line in the file will be parsed as column names. Si la codificación es NULL, se usará la codificación predeterminada.If encoding is NULL, the default encoding will be used.
SQLServerBulkCSVFileRecord(String fileToParse, boolean firstLineIsColumnNames Inicializa una instancia nueva de la clase SQLServerBulkCSVFileRecord que analizará cada línea de fileToParse con una coma como delimitador y la codificación predeterminada.Initializes a new instance of the SQLServerBulkCSVFileRecord class that will parse each line in the fileToParse with a comma as the delimiter and default encoding. Si firstLineIsColumnNames se establece en True, la primera línea del archivo se analizará como nombres de columna.If firstLineIsColumnNames is set to True, the first line in the file will be parsed as column names.
MétodoMethod DescripciónDescription
void addColumnMetadata(int positionInFile, String columnName, int jdbcType, int precision, int scale) Agrega metadatos de la columna especificada en el archivo.Adds metadata for the given column in the file.
void close() Libera los recursos asociados con el lector de archivos.Releases any resources associated with the file reader.
void setTimestampWithTimezoneFormat(DateTimeFormatter dateTimeFormatter) Establece el formato para analizar los datos Timestamp desde el archivo como java.sql.Types.TIMESTAMP_WITH_TIMEZONE.Sets the format for parsing Timestamp data from the file as java.sql.Types.TIMESTAMP_WITH_TIMEZONE.
void setTimestampWithTimezoneFormat(String dateTimeFormat) Establece el formato para analizar los datos Time desde el archivo como java.sql.Types.TIME_WITH_TIMEZONE.Sets the format for parsing Time data from the file as java.sql.Types.TIME_WITH_TIMEZONE.
void setTimeWithTimezoneFormat(DateTimeFormatter dateTimeFormatter) Establece el formato para analizar los datos Time desde el archivo como java.sql.Types.TIME_WITH_TIMEZONE.Sets the format for parsing Time data from the file as java.sql.Types.TIME_WITH_TIMEZONE.
void setTimeWithTimezoneFormat(String timeFormat) Establece el formato para analizar los datos Time desde el archivo como java.sql.Types.TIME_WITH_TIMEZONE.Sets the format for parsing Time data from the file as java.sql.Types.TIME_WITH_TIMEZONE.

Consulte tambiénSee also

Introducción al controlador JDBCOverview of the JDBC driver