Использование массового копирования с помощью JDBC DriverUsing bulk copy with the JDBC driver

СкачатьСкачать драйвер JDBCDownloadDownload JDBC Driver

Microsoft SQL Server включает популярную служебную программу командной строки bcp, позволяющую быстро выполнять массовое копирование больших файлов в таблицы или представления баз данных 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. Класс SQLServerBulkCopy позволяет создавать решения для написания кода на Java, которые предоставляют аналогичные возможности.The SQLServerBulkCopy class allows you to write code solutions in Java that provide similar functionality. Существуют другие способы загрузки данных в таблицу SQL Server (например, с помощью инструкции INSERT), но SQLServerBulkCopy делает это значительно быстрее.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.

Класс SQLServerBulkCopy можно использовать для записи данных только в таблицы SQL Server.The SQLServerBulkCopy class can be used to write data only to SQL Server tables. Но источником данных может быть не только SQL Server, а любой источник данных, если данные можно считать с помощью реализации ResultSet, RowSet или 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.

Класс SQLServerBulkCopy предоставляет следующие возможности:Using the SQLServerBulkCopy class, you can perform:

  • одну операцию массового копирования;A single bulk copy operation

  • несколько операций массового копирования;Multiple bulk copy operations

  • операцию массового копирования с транзакцией.A bulk copy operation with a transaction

Примечание

При использовании драйвера Microsoft JDBC 4.1 для SQL Server или более ранней версии (которая не поддерживает класс SQLServerBulkCopy) вместо него можно воспользоваться инструкцией SQL Server Transact-SQL BULK INSERT.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.

Пример настройки массового копированияBulk copy example setup

Класс SQLServerBulkCopy можно использовать для записи данных только в таблицы SQL Server.The SQLServerBulkCopy class can be used to write data only to SQL Server tables. В примерах кода в этой статье используется пример базы данных SQL Server с именем AdventureWorks.The code samples shown in this article use the SQL Server sample database, AdventureWorks. Чтобы не допустить изменения существующих таблиц в примерах кода, запишите данные в таблицы, которые сначала необходимо создать.To avoid altering the existing tables in the code samples, write data to tables that you create first.

Таблицы BulkCopyDemoMatchingColumns и BulkCopyDemoDifferentColumns основаны на таблице AdventureWorks Production.Products.The BulkCopyDemoMatchingColumns and BulkCopyDemoDifferentColumns tables are both based on the AdventureWorks Production.Products table. В примерах кода, использующих эти таблицы, данные из таблицы Production.Products добавляются к одной из этих таблиц-образцов.In code samples that use these tables, data is added from the Production.Products table to one of these sample tables. Таблица BulkCopyDemoDifferentColumns используется для демонстрации сопоставления столбцов из источника данных с целевой таблицей. Таблица BulkCopyDemoMatchingColumns используется в большинстве других примеров.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.

Некоторые примеры кода демонстрируют использование одного класса SQLServerBulkCopy для записи в несколько таблиц.A few of the code samples demonstrate how to use one SQLServerBulkCopy class to write to multiple tables. В этих примерах таблицы BulkCopyDemoOrderHeader и BulkCopyDemoOrderDetail используются в качестве целевых.For these samples, the BulkCopyDemoOrderHeader and BulkCopyDemoOrderDetail tables are used as the destination tables. Эти таблицы основаны на таблицах Sales.SalesOrderHeader и Sales.SalesOrderDetail в AdventureWorks.These tables are based on the Sales.SalesOrderHeader and Sales.SalesOrderDetail tables in AdventureWorks.

Примечание

Примеры кода SQLServerBulkCopy предоставляются только для демонстрации синтаксиса применения SQLServerBulkCopy.The SQLServerBulkCopy code samples are provided to demonstrate the syntax for using SQLServerBulkCopy only. Если исходная и целевая таблицы расположены в одном экземпляре SQL Server, будет проще и быстрее использовать инструкцию Transact-SQL INSERT ... Инструкция SELECT для копирования данных.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.

Настройка таблицыTable setup

Чтобы создать таблицы, необходимые для правильной работы примеров кода, выполните следующие инструкции Transact-SQL в базе данных 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]  
  

Одинарные операции массового копированияSingle bulk copy operations

Самый простой способ массового копирования SQL Server — выполнение одной операции в базе данных.The simplest approach to performing a SQL Server bulk copy operation is to perform a single operation against a database. По умолчанию операция массового копирования выполняется как изолированная, т. е. не как транзакция и без возможности отката.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.

Примечание

Если при возникновении ошибки необходимо частично или полностью отменить массовое копирование, можно использовать управляемую SQLServerBulkCopy транзакцию или выполнить операцию массового копирования в существующей транзакции.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.
Дополнительные сведения см. в статье Транзакции и операции массового копирования.For more information, see Transaction and bulk copy operations

Для массового копирования выполните следующие действия.The general steps to perform a bulk copy operation are:

  1. Подключитесь к исходному серверу и получите данные для копирования.Connect to the source server and obtain the data to be copied. Данные также могут поступать из других источников, если их можно извлечь из объекта ResultSet или реализации ISQLServerBulkRecord.Data can also come from other sources, if it can be retrieved from a ResultSet object or an ISQLServerBulkRecord implementation.

  2. Подключитесь к целевому серверу (если только не требуется, чтобы объект SQLServerBulkCopy сам установил соединение).Connect to the destination server (unless you want SQLServerBulkCopy to establish a connection for you).

  3. Создайте объект SQLServerBulkCopy, задав все необходимые свойства через setBulkCopyOptions.Create a SQLServerBulkCopy object, setting any necessary properties via setBulkCopyOptions.

  4. Вызовите метод setDestinationTableName, чтобы указать целевую таблицу для операции массовой вставки.Call the setDestinationTableName method to indicate the target table for the bulk insert operation.

  5. Вызовите один из методов writeToServer.Call one of the writeToServer methods.

  6. Кроме того, если это необходимо, можно обновить свойства через setBulkCopyOptions и снова вызвать метод writeToServer.Optionally, update properties via setBulkCopyOptions and call writeToServer again as necessary.

  7. Вызовите close или заключите код операций массового копирования в инструкцию try-with-resources.Call close, or wrap the bulk copy operations within a try-with-resources statement.

Внимание!

Мы рекомендуем, чтобы исходные и целевые типы данных столбцов совпадали.We recommend that the source and target column data types match. Если типы данных не совпадают, SQLServerBulkCopy попытается преобразовать каждое исходное значение в целевой тип данных.If the data types do not match, SQLServerBulkCopy attempts to convert each source value to the target data type. Преобразование может повлиять на производительность и может привести к непредвиденным ошибкам.Conversions can affect performance, and also can result in unexpected errors. Например, в большинстве случаев тип данных double может преобразовываться в тип данных decimal, но это происходит не всегда.For example, a double data type can be converted to a decimal data type most of the time, but not always.

ПримерExample

Следующее приложение показывает, как загрузить данные с помощью класса SQLServerBulkCopy.The following application demonstrates how to load data using the SQLServerBulkCopy class. В этом примере объект ResultSet используется, чтобы скопировать данные из таблицы Production.Product в базе данных SQL Server AdventureWorks в такую же таблицу в этой же базе данных.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.

Важно!

Этот пример не будет работать, если вы не создали рабочие таблицы, как описано в разделе Настройка таблиц.This sample will not run unless you have created the work tables as described in Table setup. Этот код предназначен только для демонстрации синтаксиса использования SQLServerBulkCopy.This code is provided to demonstrate the syntax for using SQLServerBulkCopy only. Если исходная и целевая таблицы расположены в одном экземпляре SQL Server, будет проще и быстрее использовать инструкцию Transact-SQL INSERT ... Инструкция SELECT для копирования данных.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;
    }
}

Выполнение операции массового копирования с помощью Transact-SQLPerforming a bulk copy operation using Transact-SQL

Следующий пример демонстрирует использование метода executeUpdate для выполнения инструкции BULK INSERT.The following example illustrates how to use the executeUpdate method to execute the BULK INSERT statement.

Примечание

Путь к источнику данных указан относительно сервера.The file path for the data source is relative to the server. Для успешного выполнения массового копирования у процесса сервера должен быть доступ к этому пути.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' )");
}

несколько операций массового копирования;Multiple bulk copy operations

Вы можете выполнить несколько операций массового копирования, используя один экземпляр класса SQLServerBulkCopy.You can perform multiple bulk copy operations using a single instance of a SQLServerBulkCopy class. Если между копированиями параметры операции изменяются (например, имя целевой таблицы), необходимо обновить их до последующих вызовов любого из методов writeToServer, как показано в следующем примере.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. Если значения свойств не изменяются явным образом, все они остаются такими же, как при предыдущей операции массового копирования для данного экземпляра.Unless explicitly changed, all property values remain the same as they were on the previous bulk copy operation for a given instance.

Примечание

Выполнение нескольких операций массового копирования с использованием одного экземпляра SQLServerBulkCopy обычно более эффективно, чем использование отдельного экземпляра для каждой операции.Performing multiple bulk copy operations using the same instance of SQLServerBulkCopy is usually more efficient than using a separate instance for each operation.

При выполнении нескольких операций массового копирования с одним объектом SQLServerBulkCopy не существует ограничений, касающихся совпадения или различий целевой информации в каждой операции.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. Однако для каждой записи на сервер необходимо убедиться, что связи столбцов настроены правильно.However, you must ensure that column association information is properly set each time you write to the server.

Важно!

Этот пример не будет работать, если вы не создали рабочие таблицы, как описано в разделе Настройка таблиц.This sample will not run unless you have created the work tables as described in Table setup. Этот код предназначен только для демонстрации синтаксиса использования SQLServerBulkCopy.This code is provided to demonstrate the syntax for using SQLServerBulkCopy only. Если исходная и целевая таблицы расположены в одном экземпляре SQL Server, будет проще и быстрее использовать инструкцию Transact-SQL INSERT ... Инструкция SELECT для копирования данных.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;
    }
}

Транзакции и операции массового копированияTransaction and bulk copy operations

Операции массового копирования могут выполняться как изолированные операции или как часть многошаговой транзакции.Bulk copy operations can be performed as isolated operations or as part of a multiple step transaction. В последнем случае вы можете выполнить более одной операции массового копирования в одной транзакции, а также выполнять другие операции с базами данных (такие как вставка, обновление и удаление) с возможностью фиксации или отката всей транзакции.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.

По умолчанию операция массового копирования выполняется как изолированная.By default, a bulk copy operation is performed as an isolated operation. Операция массового копирования выполняется не как транзакция и без возможности отката.The bulk copy operation occurs in a non-transacted way, with no opportunity for rolling it back. Если при возникновении ошибки необходимо частично или полностью отменить массовое копирование, можно использовать управляемую SQLServerBulkCopy транзакцию или выполнить операцию массового копирования в существующей транзакции.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.

Расширенное массовое копирование для хранилища данных AzureExtended Bulk Copy for Azure Data Warehouse

Версия драйвера 8.4.1 добавляет новое свойство соединения (sendTemporalDataTypesAsStringForBulkCopy).Driver version v8.4.1 adds a new connection property, sendTemporalDataTypesAsStringForBulkCopy. Это логическое свойство равно true по умолчанию.This boolean property is true by default.

Это свойство соединения, если задано значение false, отправит типы данных DATE, DATETIME, DATIMETIME2, DATETIMEOFFSET, SMALLDATETIME и TIME в качестве соответствующих типов вместо отправки их в виде строки.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.

Отправка временных типов данных в соответствии с их типами позволяет пользователю отправлять данные в эти столбцы для Azure Synapse Analytics (SQL DW), что было невозможным ранее, так как драйвер преобразовывал данные в строку.Sending the temporal datatypes as their respective types allows the user to send data into those columns for Azure Synapse Analytics (SQL DW), which was not possible before due to the driver converting the data into String. Отправка строковых данных во временные столбцы работает для SQL Server, так как SQL Server будет выполнять неявное преобразование для нас, но это не то же самое в случае Azure Synapse Analytics (SQL DW).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 (SQL DW).

Кроме того, даже без установки для этой строки подключения значения "false", начиная с версии 8.4.1 типы данных MONEY и SMALLMONEY будут отправляться как типы данных MONEY / SMALLMONEY, а не DECIMAL, что также позволяет выполнять операции копирования типов данных в Azure Synapse Analytics (SQL DW).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 (SQL DW).

Ограничения расширенного массового копирования для хранилища данных AzureExtended Bulk Copy for Azure Data Warehouse limitations

В настоящее время существует два ограничения.There are currently two limitations:

  1. Если для этого свойства соединения задано значение false, драйвер принимает только строковый литерал по умолчанию для каждого временного типа данных, например: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. Если это свойство соединения имеет значение false, тип столбца, указанный для массового копирования, должен учитывать диаграмму сопоставления типов данных здесь.With this connection property set to false, the column type specified for bulk copy has to respect the data type mapping chart from here. Например, ранее пользователи могли указать java.sql.Types.TIMESTAMP для выполнения операций с массовым копированием данных в столбец DATE, но если эта функция включена, они должны указать java.sql.Types.DATE, чтобы выполнить те же действия.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.

Выполнение операции массового копирования без транзакцииPerforming a non-transacted bulk copy operation

Следующее приложение показывает, что происходит, когда во время операции массового копирования без транзакции возникает ошибка.The following application shows what happens when a non-transacted bulk copy operation encounters an error partway through the operation.

В этом примере исходная и целевая таблицы содержат столбец идентификаторов с именем ProductID.In the example, the source table and destination table each include an Identity column named ProductID. Сначала код подготавливает целевую таблицу, удаляя все строки и вставляя одну строку, у которой ProductID точно существует в исходной таблице.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. По умолчанию в целевой таблице для каждой добавляемой строки создается новое значение столбца идентификаторов.By default, a new value for the Identity column is generated in the destination table for each row added. В этом примере при открытии соединения задается параметр, заставляющий процесс массовой загрузки использовать значения идентификаторов из исходной таблицы.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.

Операция массового копирования выполняется со свойством BatchSize, равным 10.The bulk copy operation is executed with the BatchSize property set to 10. Когда операция встречает недопустимую строку, вызывается исключение.When the operation encounters the invalid row, an exception is thrown. В первом примере операция массового копирования выполняется без транзакции.In this first example, the bulk copy operation is non-transacted. Фиксируются все пакеты, скопированные до появления ошибки. Пакет, содержащий повторяющийся ключ, откатывается, а операция массового копирования прерывается до обработки любых других пакетов.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.

Примечание

Этот пример не будет работать, если вы не создали рабочие таблицы, как описано в разделе Настройка таблиц.This sample will not run unless you have created the work tables as described in Table setup. Этот код предназначен только для демонстрации синтаксиса использования SQLServerBulkCopy.This code is provided to demonstrate the syntax for using SQLServerBulkCopy only. Если исходная и целевая таблицы расположены в одном экземпляре SQL Server, будет проще и быстрее использовать инструкцию Transact-SQL INSERT ... Инструкция SELECT для копирования данных.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;
    }
}

Выполнение выделенной операции массового копирования в транзакцииPerforming a dedicated bulk copy operation in a transaction

По умолчанию операция массового копирования не создает сами транзакции.By default, a bulk copy operation does not create transactions itself. Если вы хотите выполнить выделенную операцию массового копирования, создайте новый экземпляр SQLServerBulkCopy со строкой подключения.When you want to perform a dedicated bulk copy operation, create a new instance of SQLServerBulkCopy with a connection string. В этом сценарии каждый пакет операции массового копирования неявно фиксируется базой данных.In this scenario, each batch of the bulk copy operation is implicitly committed by the database. Можно установить для параметра UseInternalTransaction значение true в SQLServerBulkCopyOptions, чтобы операция массового копирования создавала транзакции, выполняя фиксацию после каждого пакета операции массового копирования.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);

Использование существующих транзакцийUsing existing transactions

Вы можете передать объект Connection с включенными транзакциями в качестве параметра конструктора SQLServerBulkCopy.You can pass a Connection object that has transactions enabled as a parameter in a SQLServerBulkCopy constructor. В этом случае операция массового копирования выполняется в существующей транзакции, а состояние транзакции не изменяется (то есть она не фиксируется и не прерывается).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). Это позволяет приложению включить операцию массового копирования в транзакцию с другими операциями базы данных.This allows an application to include the bulk copy operation in a transaction with other database operations. Если необходимо выполнить откат всей операции массового копирования из-за ошибки или если массовое копирование должно выполняться как часть большего процесса, который может быть отменен, можно выполнить откат в объекте Connection в любой момент после массового копирования.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.

Следующее приложение похоже на BulkCopyNonTransacted с одним исключением: в этом примере операция массового копирования включена в большую внешнюю транзакцию.The following application is similar to BulkCopyNonTransacted, with one exception: in this example, the bulk copy operation is included in a larger, external transaction. Если возникает ошибка нарушения первичного ключа, производится откат всей транзакции и никакие строки не добавляются в целевую таблицу.When the primary key violation error occurs, the entire transaction is rolled back and no rows are added to the destination table.

Примечание

Этот пример не будет работать, если вы не создали рабочие таблицы, как описано в разделе Настройка таблиц.This sample will not run unless you have created the work tables as described in Table setup. Этот код предназначен только для демонстрации синтаксиса использования SQLServerBulkCopy.This code is provided to demonstrate the syntax for using SQLServerBulkCopy only. Если исходная и целевая таблицы расположены в одном экземпляре SQL Server, будет проще и быстрее использовать инструкцию Transact-SQL INSERT ... Инструкция SELECT для копирования данных.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;
    }
}

Массовое копирование из CSV-файлаBulk copy from a CSV file

Следующее приложение показывает, как загрузить данные с помощью класса SQLServerBulkCopy.The following application demonstrates how to load data using the SQLServerBulkCopy class. В этом примере CSV-файл используется для копирования данных, экспортированных из таблицы Production.Product в базе данных AdventureWorks, в аналогичную таблицу в той же базе данных.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.

Важно!

Этот пример не будет работать, если вы не создали рабочие таблицы, как описано в разделе Настройка таблиц.This sample will not run unless you have created the work tables as described in Table setup to get it.

  1. ОткройтеSQL Server Management Studio и подключитесь к SQL Server с базой данных AdventureWorks.Open SQL Server Management Studio and connect to the SQL Server with the AdventureWorks database.

  2. Разверните базы данных, щелкните правой кнопкой мыши базу данных AdventureWorks, выберите Задачи и Экспорт данных.Expand the databases, right-click the AdventureWorks database, select Tasks and Export Data...

  3. Выберите Источник данных, который позволяет подключиться к SQL Server (например, SQL Server Native Client 11.0), проверьте конфигурацию и нажмите Далее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. Выберите назначение "Неструктурированный файл" и введите имя файла с путем назначения, например 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. Задайте значения Формат — "С разделителями" и Ограничитель текста — "Нет", установите флажок Имена столбцов в первой строке данных и нажмите Далее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. Установите флажок Написать запрос, указывающий данные для передачи и вновь нажмите Далее.Select Write a query to specify the data to transfer and Next. Введите инструкцию SQL SELECT ProductID, Name, ProductNumber FROM Production.Product и нажмите ДалееEnter your SQL Statement SELECT ProductID, Name, ProductNumber FROM Production.Product, and Next

  6. Проверьте конфигурацию. Можно оставить разделитель строк {CR}{LF} и разделитель столбцов — запятую {,}.Check the configuration: You can leave the Row delimiter as {CR}{LF} and Column Delimiter as Comma {,}. Выберите Изменить сопоставления… и проверьте тип данных для каждого столбца (например, целое число для ProductID и строка Юникода для других столбцов).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. Нажмите Готово и запустите экспорт.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;
    }
}

Массовое копирование с разделителями как данными в CSV-файлеBulk copy with delimiters as data in CSV file

Версия драйвера 8.4.1 добавляет новый API SQLServerBulkCSVFileRecord.setEscapeColumnDelimitersCSV(boolean).Driver version 8.4.1 adds a new API SQLServerBulkCSVFileRecord.setEscapeColumnDelimitersCSV(boolean). Если задано значение "true", будут применяться следующие правила.When set to true, the following rules will apply:

  • Каждое поле может быть заключено в двойные кавычки.Each field may or may not be enclosed in double quotes.
  • Если поля не заключены в двойные кавычки, в полях могут отсутствовать двойные кавычки.If fields are not enclosed with double quotes, then double quotes may not appear inside the fields.
  • Поля, содержащие двойные кавычки и разделители, должны быть заключены в двойные кавычки.Fields containing double quotes, and delimiters should be enclosed in double quotes.
  • Если поля заключены в двойные кавычки, то двойные кавычки внутри поля должны быть отмечены с помощью еще одной двойной кавычки перед ними.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.

Использование массового копирования со столбцами Always EncryptedBulk copy with Always Encrypted columns

Начиная с версии Microsoft JDBC Driver 6.0 для SQL Server массовое копирование поддерживается для столбцов, зашифрованных с помощью Always Encrypted.Beginning with Microsoft JDBC Driver 6.0 for SQL Server, bulk copy is supported with Always Encrypted columns.

В зависимости от параметров массового копирования, а также типа шифрования исходной и конечной таблиц драйвер JDBC может осуществлять прозрачное шифрование данных с последующей расшифровкой либо отправлять зашифрованные данные "как есть".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. Например, при массовом копировании данных из зашифрованного столбца в незашифрованный драйвер прозрачным образом расшифровывает данные перед их отправкой в 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. Аналогичным образом, при массовом копировании данных из незашифрованного столбца (или из файла CSV) в зашифрованный драйвер прозрачным образом зашифровывает данные перед их отправкой в 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. Если зашифрованы и исходный и конечный столбец, то в зависимости от значения параметра массового копирования allowEncryptedValueModifications драйвер будет отправлять данные "как есть" или расшифровывать данные, а затем снова зашифровывать их перед отправкой в 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.

Дополнительные сведения см. в описании параметра массового копирования allowEncryptedValueModifications ниже и в статье Использование функции Always Encrypted с драйвером JDBC.For more information, see the allowEncryptedValueModifications bulk copy option below, and Using Always Encrypted with the JDBC Driver.

Важно!

При использовании Microsoft JDBC Driver 6.0 для SQL Server с целью массового копирования данных из файла CSV в зашифрованные столбцы действуют указанные ниже ограничения.Limitation of the Microsoft JDBC Driver 6.0 for SQL Server, when bulk copying data from a CSV file to encrypted columns:

Для типов даты и времени поддерживается только формат строковых литералов Transact-SQL по умолчанию.Only the Transact-SQL default string literal format is supported for the date and time types

Типы данных DATETIME и SMALLDATETIME не поддерживаются.DATETIME and SMALLDATETIME data types are not supported

Массовое копирование API для драйвера JDBCBulk copy API for JDBC driver

SQLServerBulkCopySQLServerBulkCopy

Позволяет эффективно выполнять массовую загрузку таблицы SQL Server с данными из другого источника.Lets you efficiently bulk-load a SQL Server table with data from another source.

Microsoft SQL Server включает популярную программу командной строки bcp, используемую для перемещения данных из одной таблицы в другую как на одном сервере, так и между серверами.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. Класс SQLServerBulkCopy позволяет создавать решения на языке Java, которые предоставляют аналогичные возможности.The SQLServerBulkCopy class lets you write code solutions in Java that provide similar functionality. Существуют другие способы загрузки данных в таблицу SQL Server (например, с помощью инструкции INSERT), но SQLServerBulkCopy делает это значительно быстрее.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.

Класс SQLServerBulkCopy можно использовать для записи данных только в таблицы SQL Server.The SQLServerBulkCopy class can be used to write data only to SQL Server tables. Однако источником данных может быть не только SQL Server, а любой источник данных, если данные можно считать с помощью экземпляра ResultSet или реализации 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.

КонструкторConstructor ОписаниеDescription
SQLServerBulkCopy(Connection connection) Инициализирует новый экземпляр класса SQLServerBulkCopy, используя указанный открытый экземпляр SQLServerConnection.Initializes a new instance of the SQLServerBulkCopy class using the specified open instance of SQLServerConnection. Если для объекта Connection включены транзакции, операции копирования будут выполняться в контексте этой транзакции.If the Connection has transactions enabled, the copy operations will be performed within that transaction.
SQLServerBulkCopy(String connectionURL) Инициализирует и открывает новый экземпляр класса SQLServerConnection в зависимости от предоставленного параметра connectionURL.Initializes and opens a new instance of SQLServerConnection based on the supplied connectionURL. Конструктор использует SQLServerConnection для инициализации нового экземпляра класса SQLServerBulkCopy.The constructor uses the SQLServerConnection to initialize a new instance of the SQLServerBulkCopy class.
СвойствоProperty ОписаниеDescription
String DestinationTableName Имя целевой таблицы на сервере.Name of the destination table on the server.

Если DestinationTableName не было задано при вызове writeToServer, создается исключение SQLServerException.If DestinationTableName hasn't been set when writeToServer is called, a SQLServerException is thrown.

DestinationTableName — это трехкомпонентное имя (<database>.<owningschema>.<name>).DestinationTableName is a three-part name (<database>.<owningschema>.<name>). При необходимости можно уточнить имя таблицы с помощью указания базы данных и схемы-владельца.You can qualify the table name with its database and owning schema if you choose. Но если имя таблицы содержит символ подчеркивания («_») или другие специальные символы, необходимо заключить имя в скобки.However, if the table name uses an underscore ("_") or any other special characters, you must escape the name using surrounding brackets. Дополнительные сведения см. в разделе Идентификаторы баз данных.For more information, see Database Identifiers.
ColumnMappings Сопоставления столбцов определяют связи между столбцами в источнике данных и столбцами в месте назначения.Column mappings define the relationships between columns in the data source and columns in the destination.

Если сопоставления не определены, столбцы сопоставляются неявно по порядковому номеру.If mappings aren't defined, the columns are mapped implicitly based on ordinal position. При этом исходная и целевая схемы должны совпадать.For this to work, source and target schemas must match. Иначе будет вызвано исключение.If they don't, an Exception will be thrown.

Если сопоставления не пусты, не обязательно задавать все столбцы, присутствующие в источнике данных.If the mappings isn't empty, not every column present in the data source has to be specified. Несопоставленные столбцы будут проигнорированы.Those not mapped are ignored.

Обращаться к исходным и целевым столбцам можно по имени или порядковому номеру.You can refer to source and target columns by either name or ordinal.
МетодMethod ОписаниеDescription
void addColumnMapping(int sourceColumn, int destinationColumn) Добавляет новое сопоставление столбцов, используя порядковые номера исходного и целевого столбцов.Adds a new column-mapping, using ordinals to specify both source and destination columns.
void addColumnMapping (int sourceColumn, String destinationColumn) Добавляет новое сопоставление столбцов, используя порядковый номер исходного столбца и имя целевого столбца.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) Добавляет новое сопоставление столбцов, используя имя исходного столбца и порядковый номер целевого столбца.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) Добавляет новое сопоставление столбцов, используя имена исходного и целевого столбцов.Adds a new column-mapping, using column names to specify both source and destination columns.
void clearColumnMappings() Очищает содержимое сопоставления столбцов.Clears the contents of the column mappings.
void close() Закрывает экземпляр SQLServerBulkCopy.Closes the SQLServerBulkCopy instance.
SQLServerBulkCopyOptions getBulkCopyOptions() Извлекает текущий набор SQLServerBulkCopyOptions.Retrieves the current set of SQLServerBulkCopyOptions.
String getDestinationTableName() Получает имя текущей целевой таблицы.Retrieve the current destination table name.
void setBulkCopyOptions(SQLServerBulkCopyOptions copyOptions) Обновляет поведение экземпляра SQLServerBulkCopy в соответствии с предоставленными параметрами.Updates the behavior of the SQLServerBulkCopy instance according to the options supplied.
void setDestinationTableName(String tableName) Задает имя целевой таблицы.Sets the name of the destination table.
void writeToServer(ResultSet sourceData) Копирует все строки в предоставленном ResultSet в целевую таблицу, заданную свойством DestinationTableName объекта 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) Копирует все строки в предоставленном RowSet в целевую таблицу, заданную свойством DestinationTableName объекта 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) Копирует все строки в предоставленной реализации ISQLServerBulkRecord в целевую таблицу, заданную свойством DestinationTableName объекта SQLServerBulkCopy.Copies all rows in the supplied ISQLServerBulkRecord implementation to a destination table specified by the DestinationTableName property of the SQLServerBulkCopy object.

SQLServerBulkCopyOptionsSQLServerBulkCopyOptions

Коллекция параметров, которые управляют поведением методов writeToServer в экземпляре SQLServerBulkCopy.A collection of settings that control how the writeToServer methods behave in an instance of SQLServerBulkCopy.

КонструкторConstructor ОписаниеDescription
SQLServerBulkCopyOptions() Инициализирует новый экземпляр класса SQLServerBulkCopyOptions, используя для всех параметров значения по умолчанию.Initializes a new instance of the SQLServerBulkCopyOptions class using defaults for all of the settings.

Методы get и set существуют для следующих параметров.Getters and setters exist for the following options:

ПараметрOption ОписаниеDescription Значение по умолчаниюDefault
boolean CheckConstraints Проверка ограничений при вставке данных.Check constraints while data is being inserted. False — ограничения не проверяются.False - constraints aren't checked
boolean FireTriggers Сервер запускает триггеры вставки для строк, вставляемых в базу данных.Cause the server to fire the insert triggers for the rows being inserted into the database. False — триггеры не выполняются.False - no triggers are fired
boolean KeepIdentity Сохранять идентификационные значения источника.Preserve source identity values. False — значения идентификаторов назначаются целевым объектом.False - identity values are assigned by the destination
boolean KeepNulls Сохранять значения null в целевой таблице независимо от значений параметров по умолчанию.Preserve null values in the destination table regardless of the settings for default values. False — значения null заменяются значениями по умолчанию, где это применимо.False - null values are replaced by default values where applicable.
boolean TableLock Применить блокировку массового обновления на время операции массового копирования.Obtain a bulk update lock for the duration of the bulk copy operation. False — блокировки строк используются.False - row locks are used.
boolean UseInternalTransaction Если этот параметр имеет значение true, каждый пакет операции массового копирования будет выполняться в рамках транзакции.When set to true, each batch of the bulk-copy operation will occur within a transaction. Если SQLServerBulkCopy использует существующее подключение (как указано конструктором), вызывается исключение SQLServerException.If SQLServerBulkCopy is using an existing connection (as specified by the constructor), a SQLServerException will occur. Если SQLServerBulkCopy создает выделенное соединение, транзакция будет создана и зафиксирована для каждого пакета.If SQLServerBulkCopy created a dedicated connection, a transaction will be created and committed for each batch. False — транзакция отсутствует.False - no transaction
int BatchSize Количество строк в каждом пакете.Number of rows in each batch. В конце каждого пакета строки из пакета передаются на сервер.At the end of each batch, the rows in the batch are sent to the server.

Пакет завершается, когда число обработанных строк равно BatchSize или отсутствуют строки для отправки в целевой источник данных.A batch is complete when BatchSize rows have been processed or there are no more rows to send to the destination data source. Если экземпляр SQLServerBulkCopy объявлен с параметром UseInternalTransaction, для которого указано значение false, строки отправляются на сервер по BatchSize строк за раз, но действия, связанные с транзакциями, не выполняются.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. Если UseInternalTransaction имеет значение true, каждый пакет строк выполняется в явной транзакции.If UseInternalTransaction is set to true, each batch of rows is performed within an explicit transaction.
Значение 0 указывает, что каждая операция writeToServer представляет один пакет.0 - indicates that each writeToServer operation is a single batch
int BulkCopyTimeout Время выполнения операции до истечения времени ожидания в секундах. Значение 0 означает отсутствие ограничений; операция массового копирования будет находиться в ожидании бесконечно долго.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 секунд.60 seconds.
boolean allowEncryptedValueModifications Этот параметр доступен в Microsoft JDBC Driver 6.0 (или более поздней версии) для SQL Server.This option is available with Microsoft JDBC Driver 6.0 (or higher) for SQL Server.

Если задано значение true, allowEncryptedValueModifications позволяет пользователю массово копировать зашифрованные данные между таблицами или базами данных без расшифровки данных.When set to true, allowEncryptedValueModifications enables bulk copying of encrypted data between tables or databases, without decrypting the data. Как правило, приложение выбирает данные из зашифрованных столбцов в одной таблице, не расшифровывая их (для подключения к базе данных используется ключевое слово Column Encryption Setting со значением Disabled), а затем с помощью этого параметра выполняет массовую вставку данных, которые по-прежнему зашифрованы.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. Дополнительные сведения: Использование функции Always Encrypted с драйвером JDBC.For more information, see Using Always Encrypted with the JDBC Driver.

Задавайте для параметра allowEncryptedValueModifications значение true с осторожностью. Драйвер не проверяет, являются ли данные зашифрованными и используются ли при шифровании те же тип, алгоритм и ключ шифрования, что у целевого столбца. Поэтому изменение значений может повредить базу данных.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.

Методы получения и методы задания:Getters and setters:

МетодыMethods ОписаниеDescription
boolean isCheckConstraints() Показывает, должны ли проверяться ограничения при вставке данных.Indicates whether constraints are to be checked while data is being inserted or not.
void setCheckConstraints(boolean checkConstraints) Определяет, должны ли проверяться ограничения при вставке данных.Sets whether constraints are to be checked while data is being inserted or not.
boolean isFireTriggers() Показывает, должен ли сервер выполнять триггеры вставки для строк, вставляемых в базу данных.Indicates if the server should fire the insert triggers for the rows being inserted into the database.
void setFireTriggers(boolean fireTriggers) Определяет, должен ли сервер выполнять триггеры вставки для строк, вставляемых в базу данных.Sets whether the server should be set to fire triggers for the rows being inserted into the database.
boolean isKeepIdentity() Показывает, должны ли сохраняться исходные значения идентификаторов.Indicates whether or not to preserve any source identity values.
void setKeepIdentity(boolean keepIdentity) Определяет, должны ли сохраняться значения идентификаторов.Sets whether or not to preserve identity values.
boolean isKeepNulls() Показывает, должны ли сохраняться значения NULL в конечной таблице независимо от значений параметров по умолчанию или они должны заменяться значениями по умолчанию (если это возможно).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) Определяет, должны ли сохраняться значения NULL в конечной таблице независимо от значений параметров по умолчанию или они должны заменяться значениями по умолчанию (если это возможно).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() Показывает, должен ли объект SQLServerBulkCopy получать блокировку массового изменения на время операции массового копирования.Indicates whether SQLServerBulkCopy should obtain a bulk update lock for the duration of the bulk copy operation.
void setTableLock(boolean tableLock) Указывает, должен ли объект SQLServerBulkCopy получать блокировку массового изменения на время операции массового копирования.Sets whether SQLServerBulkCopy should obtain a bulk update lock for the duration of the bulk copy operation.
boolean isUseInternalTransaction() Указывает, должен ли каждый пакет операции массового копирования выполняться в рамках транзакции.Indicates whether each batch of the bulk-copy operation will occur within a transaction.
void setUseInternalTranscation(boolean useInternalTransaction) Указывает, должен ли каждый пакет операции массового копирования выполняться в рамках транзакции.Sets whether each batch of the bulk-copy operations will occur within a transaction or not.
int getBatchSize() Получает число строк в каждом пакете.Gets the number of rows in each batch. В конце каждого пакета строки из пакета передаются на сервер.At the end of each batch, the rows in the batch are sent to the server.
void setBatchSize(int batchSize) Задает число строк в каждом пакете.Sets the number of rows in each batch. В конце каждого пакета строки из пакета передаются на сервер.At the end of each batch, the rows in the batch are sent to the server.
int getBulkCopyTimeout() Получает время выполнения операции до истечения времени ожидания, в секундах.Gets the number of seconds for the operation to complete before it times out.
void setBulkCopyTimeout(int timeout) Задает время выполнения операции до истечения времени ожидания, в секундах.Sets the number of seconds for the operation to complete before it times out.
boolean isAllowEncryptedValueModifications() Указывает, включен или выключен параметр allowEncryptedValueModifications.Indicates whether allowEncryptedValueModifications setting is enabled or disabled.
void setAllowEncryptedValueModifications(boolean allowEncryptedValueModifications) Настраивает параметр allowEncryptedValueModifications, используемый для массового копирования столбцов Always Encrypted.Configures the allowEncryptedValueModifications setting that is used for bulk copy with Always Encrypted columns.

ISQLServerBulkRecordISQLServerBulkRecord

Интерфейс ISQLServerBulkRecord можно использовать для создания классов, которые считывают данные из любого источника (например, файла), чтобы позволить экземпляру SQLServerBulkCopy выполнить массовую загрузку данных таблицы SQL Server.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.

Методы интерфейсаInterface Methods ОписаниеDescription
set<Integer> getColumnOrdinals() Получение порядковых номеров столбцов, представленных в этой записи данных.Get the ordinals for each of the columns represented in this data record.
String getColumnName(int column) Получение имени заданного столбца.Get the name of the given column.
int getColumnType(int column) Получение типа данных JDBC заданного столбца.Get the JDBC data type of the given column.
int getPrecision(int column) Получение точности для данного столбца.Get the precision for the given column.
object[] getRowData() Возвращает данные для текущей строки как массив объектов.Gets the data for the current row as an array of Objects.

Тип каждого объекта должен соответствовать типу Java, используемому для представления указанного типа данных JDBC этого столбца.Each Object must match the Java language Type that is used to represent the indicated JDBC data type for the given column. Дополнительные сведения см. в разделе Основные сведения о типах данных драйвера JDBC для соответствующих сопоставлений.For more information, see Understanding the JDBC Driver Data Types for the appropriate mappings.
int getScale(int column) Получение масштаба для данного столбца.Get the scale for the given column.
boolean isAutoIncrement(int column) Обозначает, содержит ли столбец идентификаторы.Indicates whether the column represents an identity column.
boolean next() Переход на следующую строку данных.Advances to the next data row.

SQLServerBulkCSVFileRecordSQLServerBulkCSVFileRecord

Простая реализация интерфейса ISQLServerBulkRecord, которая может использоваться для чтения базовых типов данных Java из файла с разделителями, где каждая строка представляет строку данных.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.

Примечания по реализации и ограниченияImplementation Notes and Limitations:

  1. Максимальный объем данных в любой строке ограничивается объемом доступной памяти, поскольку данные считываются по одной строке за раз.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. Потоковая передача больших типов данных, таких как varchar(max), varbinary(max), nvarchar(max), sqlxml и ntext, не поддерживается.Streaming of large data types such as varchar(max), varbinary(max), nvarchar(max), sqlxml, and ntext isn't supported.

  3. Разделитель, указанный для CSV-файла, не должен содержаться в данных и, если это зарезервированный символ, должен быть надлежащим образом экранирован в регулярных выражениях 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. В реализации CSV-файла двойные кавычки рассматриваются как часть данных.In the CSV file implementation, double quotes are treated as part of the data. Например, строка hello,"world","hello,world" будет рассматриваться как строка с четырьмя столбцами со значениями hello, "world", "hello и 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. Символы новой строки используются в качестве признака конца строки и не допускаются в данных.New line characters are used as row terminators and aren't allowed anywhere in the data.

КонструкторConstructor ОписаниеDescription
SQLServerBulkCSVFileRecord(String fileToParse, String encoding, String delimiter, boolean firstLineIsColumnNames) Инициализирует новый экземпляр класса SQLServerBulkCSVFileRecord, который будет выполнять синтаксический анализ каждой строки в fileToParse с указанными разделителем и кодировкой.Initializes a new instance of the SQLServerBulkCSVFileRecord class that will parse each line in the fileToParse with the provided delimiter and encoding. Если firstLineIsColumnNames имеет значение True, первая строка файла будет проанализирована как имена столбцов.If firstLineIsColumnNames is set to True, the first line in the file will be parsed as column names. Если кодировка имеет значение NULL, будет использоваться кодировка по умолчанию.If encoding is NULL, the default encoding will be used.
SQLServerBulkCSVFileRecord(String fileToParse, String encoding, boolean firstLineIsColumnNames) Инициализирует новый экземпляр класса SQLServerBulkCSVFileRecord, который будет выполнять синтаксический анализ каждой строки в fileToParse с разделителем запятой и предоставленной кодировкой.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. Если firstLineIsColumnNames имеет значение True, первая строка файла будет проанализирована как имена столбцов.If firstLineIsColumnNames is set to True, the first line in the file will be parsed as column names. Если кодировка имеет значение NULL, будет использоваться кодировка по умолчанию.If encoding is NULL, the default encoding will be used.
SQLServerBulkCSVFileRecord(String fileToParse, boolean firstLineIsColumnNames Инициализирует новый экземпляр класса SQLServerBulkCSVFileRecord, который будет выполнять синтаксический анализ каждой строки в fileToParse с разделителем запятой и кодировкой по умолчанию.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. Если firstLineIsColumnNames имеет значение True, первая строка файла будет проанализирована как имена столбцов.If firstLineIsColumnNames is set to True, the first line in the file will be parsed as column names.
МетодMethod ОписаниеDescription
void addColumnMetadata(int positionInFile, String columnName, int jdbcType, int precision, int scale) Добавляет метаданные для указанного столбца в файле.Adds metadata for the given column in the file.
void close() Освобождает все ресурсы, связанные со средством чтения файла.Releases any resources associated with the file reader.
void setTimestampWithTimezoneFormat(DateTimeFormatter dateTimeFormatter) Задает формат для синтаксического анализа данных отметки времени из файла как 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) Задает формат для синтаксического анализа данных времени из файла как 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) Задает формат для синтаксического анализа данных времени из файла как 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) Задает формат для синтаксического анализа данных времени из файла как java.sql.Types.TIME_WITH_TIMEZONE.Sets the format for parsing Time data from the file as java.sql.Types.TIME_WITH_TIMEZONE.

См. также разделSee also

Общие сведения о JDBC DriverOverview of the JDBC driver