언어
SQL Server 대량 복사 작업을 수행하는 가장 간단한 접근 방식은 데이터베이스에 단일 작업을 수행하는 것입니다. 기본적으로 대량 복사 작업은 격리된 작업으로 수행됩니다. 복사 작업은 트랜잭션되지 않은 방식으로 수행되어 롤백할 수 없습니다.
참고
오류 발생 후 대량 복사의 전체 또는 일부를 롤백하려면 일괄 처리별 트랜잭션에 대해 SqlBulkCopyOptions.UseInternalTransaction을 지정하거나 기존 트랜잭션 내에서 복사를 수행하십시오.
SqlBulkCopy은 연결이 암시적으로 또는 명시적으로 인리스트되는 경우 System.Transactions과도 작동합니다.
자세한 내용은 트랜잭션 및 대량 복사 작업을 참조하세요.
대량 복사 작업을 수행하는 일반적인 단계는 다음과 같습니다.
소스 서버에 연결하고 복사할 데이터를 가져옵니다. IDataReader 또는 DataTable 개체에서 데이터를 검색할 수 있는 경우, 다른 원본에서 데이터를 가져올 수도 있습니다.
목적지 서버에 연결합니다. 단,
SqlBulkCopy가 연결을 설정하도록 하려면 연결하지 마세요.개체를 SqlBulkCopy 만들고 필요한 속성을 설정합니다.
DestinationTableName대량 삽입 작업의 대상 테이블을 나타내도록 속성을 설정합니다.메서드 중 하나를 호출합니다
WriteToServer.필요에 따라 속성을 업데이트한 후
WriteToServer를 다시 호출합니다.Close를 호출하거나 대량 복사 작업을
Using문 내에 래핑합니다.
주의
일치하는 원본 및 대상 열 데이터 형식을 사용합니다. 형식이 일치하지 않으면 SqlBulkCopy 각 원본 값을 Value의 규칙에 따라 대상 데이터 형식으로 변환하려고 합니다. 변환은 성능에 영향을 미치고 예기치 않은 오류를 일으킬 수 있습니다. 예를 들어 Double에서 Decimal로의 변환은 일부 값에서 실패할 수 있습니다.
예시
다음 콘솔 애플리케이션은 SqlBulkCopy 클래스를 사용하여 데이터를 로드하는 방법을 보여 줍니다. 이 예제에서는 SqlDataReader를 사용하여 SQL Server Production.Product 데이터베이스의 AdventureWorks에서 데이터를 동일한 데이터베이스의 유사한 테이블로 복사합니다.
중요한
이 샘플을 실행하기 전에 대량 복사 예제 설정에 설명된 작업 테이블을 만듭니다. 이 샘플에서는 SqlBulkCopy 구문을 보여 줍니다. 원본 테이블과 대상 테이블이 동일한 SQL Server 인스턴스에 있는 경우 빠른 복사를 위해 Transact-SQL(T-SQL) INSERT ... SELECT 문을 사용합니다.
static void Main()
{
var connectionString = GetConnectionString();
// Open a sourceConnection to the AdventureWorks database.
using (SqlConnection sourceConnection =
new(connectionString))
{
sourceConnection.Open();
// Perform an initial count on the destination table.
SqlCommand commandRowCount = new(
"SELECT COUNT(*) FROM " +
"dbo.BulkCopyDemoMatchingColumns;",
sourceConnection);
long countStart = Convert.ToInt32(
commandRowCount.ExecuteScalar());
Console.WriteLine($"Starting row count = {countStart}");
// Get data from the source table as a SqlDataReader.
SqlCommand commandSourceData = new(
"SELECT ProductID, Name, " +
"ProductNumber " +
"FROM Production.Product;", sourceConnection);
SqlDataReader reader =
commandSourceData.ExecuteReader();
// Open the destination connection. In the real world you would
// not use SqlBulkCopy to move data from one table to the other
// in the same database. This is for demonstration purposes only.
using (SqlConnection destinationConnection =
new(connectionString))
{
destinationConnection.Open();
// Set up the bulk copy object.
// Note that the column positions in the source
// data reader match the column positions in
// the destination table so there is no need to
// map columns.
using (SqlBulkCopy bulkCopy =
new(destinationConnection))
{
bulkCopy.DestinationTableName =
"dbo.BulkCopyDemoMatchingColumns";
try
{
// Write from the source to the destination.
bulkCopy.WriteToServer(reader);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
// Close the SqlDataReader. The SqlBulkCopy
// object is automatically closed at the end
// of the using block.
reader.Close();
}
}
// Perform a final count on the destination
// table to see how many rows were added.
long countEnd = Convert.ToInt32(
commandRowCount.ExecuteScalar());
Console.WriteLine($"Ending row count = {countEnd}");
Console.WriteLine($"{countEnd - countStart} rows were added.");
Console.WriteLine("Press Enter to finish.");
Console.ReadLine();
}
}
}
Imports Microsoft.Data.SqlClient
Module Module1
Sub Main()
Dim connectionString As String = GetConnectionString()
' Open a connection to the AdventureWorks database.
Using sourceConnection As SqlConnection = _
New SqlConnection(connectionString)
sourceConnection.Open()
' Perform an initial count on the destination table.
Dim commandRowCount As New SqlCommand( _
"SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", _
sourceConnection)
Dim countStart As Long = _
System.Convert.ToInt32(commandRowCount.ExecuteScalar())
Console.WriteLine("Starting row count = {0}", countStart)
' Get data from the source table as a SqlDataReader.
Dim commandSourceData As New SqlCommand( _
"SELECT ProductID, Name, ProductNumber " & _
"FROM Production.Product;", sourceConnection)
Dim reader As SqlDataReader = commandSourceData.ExecuteReader
' Open the destination connection. In the real world you would
' not use SqlBulkCopy to move data from one table to the other
' in the same database. This is for demonstration purposes only.
Using destinationConnection As SqlConnection = _
New SqlConnection(connectionString)
destinationConnection.Open()
' Set up the bulk copy object.
' The column positions in the source data reader
' match the column positions in the destination table,
' so there is no need to map columns.
Using bulkCopy As SqlBulkCopy = _
New SqlBulkCopy(destinationConnection)
bulkCopy.DestinationTableName = _
"dbo.BulkCopyDemoMatchingColumns"
Try
' Write from the source to the destination.
bulkCopy.WriteToServer(reader)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
' Close the SqlDataReader. The SqlBulkCopy
' object is automatically closed at the end
' of the Using block.
reader.Close()
End Try
End Using
' Perform a final count on the destination table
' to see how many rows were added.
Dim countEnd As Long = _
System.Convert.ToInt32(commandRowCount.ExecuteScalar())
Console.WriteLine("Ending row count = {0}", countEnd)
Console.WriteLine("{0} rows were added.", countEnd - countStart)
Console.WriteLine("Press Enter to finish.")
Console.ReadLine()
End Using
End Using
End Sub
Private Function GetConnectionString() As String
Throw New NotImplementedException()
End Function
End Module
Transact-SQL 및 Command 클래스를 사용하여 대량 복사 작업 수행
다음 예제에서는 ExecuteNonQuery 메서드를 사용하여 BULK INSERT 문을 실행하는 방법을 보여 줍니다.
참고
데이터 소스의 파일 경로는 서버에 대해 상대적입니다. 대량 복사 작업이 성공하려면 서버 프로세스에서 해당 경로에 액세스할 수 있어야 합니다.
Using connection As SqlConnection = New SqlConnection(connectionString)
Dim queryString As String = _
"BULK INSERT Northwind.dbo.[Order Details] FROM " & _
"'f:\mydata\data.tbl' WITH (FORMATFILE='f:\mydata\data.fmt' )"
connection.Open()
Dim command As New SqlCommand(queryString, connection)
command.ExecuteNonQuery()
End Using
using (SqlConnection connection = new SqlConnection(connectionString))
{
string queryString = "BULK INSERT Northwind.dbo.[Order Details] " +
@"FROM 'f:\mydata\data.tbl' " +
@"WITH ( FORMATFILE='f:\mydata\data.fmt' )";
connection.Open();
SqlCommand command = new SqlCommand(queryString, connection);
command.ExecuteNonQuery();
}