단일 대량 복사 작업(ADO.NET)
SQL Server 대량 복사 작업을 수행하는 가장 간단한 접근 방식은 데이터베이스에 단일 작업을 수행하는 것입니다. 기본적으로 대량 복사 작업은 격리된 작업으로 수행됩니다. 복사 작업은 롤백할 수 없는 비트랜잭트 방식으로 이루어집니다.
참고 |
---|
오류가 발생할 때 대량 복사의 전체 또는 일부를 롤백해야 하는 경우에는 SqlBulkCopy에서 관리되는 트랜잭션을 사용하거나 기존 트랜잭션 내에서 대량 복사 작업을 수행할 수 있습니다.연결이 System.Transactions 트랜잭션에 암시적으로나 명시적으로 인리스트먼트된 경우 SqlBulkCopy에서도 System.Transactions을 사용합니다. 자세한 내용은 트랜잭션 및 대량 복사 작업(ADO.NET)을 참조하십시오. |
일반적으로 대량 복사 작업을 수행하는 단계는 다음과 같습니다.
소스 서버에 연결하고 복사할 데이터를 가져옵니다. 데이터를 IDataReader 또는 DataTable 개체에서 검색할 수 있으면 다른 소스에서 가져올 수도 있습니다.
SqlBulkCopy를 통해 자동으로 연결하지 않으려는 경우 대상 서버에 연결합니다.
SqlBulkCopy 개체를 만들고 필요한 속성을 설정합니다.
DestinationTableName 속성이 대량 삽입 작업의 대상 테이블을 나타내도록 설정합니다.
WriteToServer 메서드 중 하나를 호출합니다.
필요에 따라 속성을 업데이트하고 WriteToServer를 다시 호출합니다.
Close를 호출하거나 대량 복사 작업을 Using 문 내에 래핑합니다.
주의 |
---|
소스 열과 대상 열의 데이터 형식은 일치하는 것이 좋습니다.데이터 형식이 일치하지 않으면 SqlBulkCopy는 Value에서 사용되는 규칙과 동일한 규칙을 사용하여 각 소스 값을 대상 데이터 형식으로 변환하려고 시도합니다.변환을 수행하면 성능에 영향을 줄 뿐 아니라 예기치 않은 오류가 발생할 수도 있습니다.예를 들어, Double 데이터 형식은 일반적으로 Decimal 데이터 형식으로 변환되지만 항상 그런 것은 아닙니다. |
예제
다음 콘솔 응용 프로그램에서는 SqlBulkCopy 클래스를 사용하여 데이터를 로드하는 방법을 보여 줍니다. 이 예제에서는 SqlDataReader를 사용하여 SQL Server 2005 AdventureWorks 데이터베이스에 있는 Production.Product 테이블의 데이터를 같은 데이터베이스의 비슷한 테이블로 복사합니다.
중요 |
---|
대량 복사 예제 설정(ADO.NET)에서 설명한 것처럼 작업 테이블을 만들지 않은 경우 이 샘플은 실행되지 않습니다.이 코드는 SqlBulkCopy를 사용하는 구문을 보여 주는 용도로 제공됩니다.소스 테이블과 대상 테이블이 동일한 SQL Server 인스턴스에 있으면 Transact-SQL INSERT … SELECT 문을 사용하여 데이터를 더 쉽고 빠르게 복사할 수 있습니다. |
Imports System.Data.SqlClient
Module Module1
Sub Main()
Dim connectionString As String = GetConnectionString()
' Open a connection to the AdventureWorks database.
Using sourceConnection As SqlConnection = _
New SqlConnection(connectionString)
sourceConnection.Open()
' Perform an initial count on the destination table.
Dim commandRowCount As New SqlCommand( _
"SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", _
sourceConnection)
Dim countStart As Long = _
System.Convert.ToInt32(commandRowCount.ExecuteScalar())
Console.WriteLine("Starting row count = {0}", countStart)
' Get data from the source table as a SqlDataReader.
Dim commandSourceData As SqlCommand = New SqlCommand( _
"SELECT ProductID, Name, ProductNumber " & _
"FROM Production.Product;", sourceConnection)
Dim reader As SqlDataReader = commandSourceData.ExecuteReader
' Open the destination connection. In the real world you would
' not use SqlBulkCopy to move data from one table to the other
' in the same database. This is for demonstration purposes only.
Using destinationConnection As SqlConnection = _
New SqlConnection(connectionString)
destinationConnection.Open()
' Set up the bulk copy object.
' The column positions in the source data reader
' match the column positions in the destination table,
' so there is no need to map columns.
Using bulkCopy As SqlBulkCopy = _
New SqlBulkCopy(destinationConnection)
bulkCopy.DestinationTableName = _
"dbo.BulkCopyDemoMatchingColumns"
Try
' Write from the source to the destination.
bulkCopy.WriteToServer(reader)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
' Close the SqlDataReader. The SqlBulkCopy
' object is automatically closed at the end
' of the Using block.
reader.Close()
End Try
End Using
' Perform a final count on the destination table
' to see how many rows were added.
Dim countEnd As Long = _
System.Convert.ToInt32(commandRowCount.ExecuteScalar())
Console.WriteLine("Ending row count = {0}", countEnd)
Console.WriteLine("{0} rows were added.", countEnd - countStart)
Console.WriteLine("Press Enter to finish.")
Console.ReadLine()
End Using
End Using
End Sub
Private Function GetConnectionString() As String
' To avoid storing the sourceConnection string in your code,
' you can retrieve it from a configuration file.
Return "Data Source=(local);" & _
"Integrated Security=true;" & _
"Initial Catalog=AdventureWorks;"
End Function
End Module
using System.Data.SqlClient;
class Program
{
static void Main()
{
string connectionString = GetConnectionString();
// Open a sourceConnection to the AdventureWorks database.
using (SqlConnection sourceConnection =
new SqlConnection(connectionString))
{
sourceConnection.Open();
// Perform an initial count on the destination table.
SqlCommand commandRowCount = new SqlCommand(
"SELECT COUNT(*) FROM " +
"dbo.BulkCopyDemoMatchingColumns;",
sourceConnection);
long countStart = System.Convert.ToInt32(
commandRowCount.ExecuteScalar());
Console.WriteLine("Starting row count = {0}", countStart);
// Get data from the source table as a SqlDataReader.
SqlCommand commandSourceData = new SqlCommand(
"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 SqlConnection(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 SqlBulkCopy(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 = 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();
}
}
}
private static string GetConnectionString()
// To avoid storing the sourceConnection string in your code,
// you can retrieve it from a configuration file.
{
return "Data Source=(local); " +
" Integrated Security=true;" +
"Initial Catalog=AdventureWorks;";
}
}
Transact-SQL 및 Command 클래스를 사용하여 대량 복사 작업 수행
SqlBulkCopy 클래스를 지원하지 않는 .NET Framework 버전 1.1 이하를 사용하는 경우 SqlCommand 개체를 사용하여 Transact-SQL BULK INSERT 문을 실행할 수도 있습니다. 이 기법을 사용하는 것은 .NET Framework Data Provider for SQL Server에서 제공하는 대량 복사 기능을 사용하는 것과 전혀 관련이 없습니다.
다음 예제에서는 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()
SqlCommand command = New SqlCommand(queryString, connection);
command.ExecuteNonQuery()
End Using
using (SqlConnection connection = New SqlConnection(connectionString))
{
string queryString = "BULK INSERT Northwind.dbo.[Order Details] " +
"FROM 'f:\mydata\data.tbl' " +
"WITH ( FORMATFILE='f:\mydata\data.fmt' )";
connection.Open();
SqlCommand command = new SqlCommand(queryString, connection);
command.ExecuteNonQuery();
}