1.1 SqlBulkCopyOptions.KeepIdentity 必須設置!否則會出現復制過去的數據產生標識列發現變化的情況!
1.2 如果原表的標識列即為主鍵, 那按1.1 的設置已足夠。 如果原表無主鍵, 那在復制之前必須先清空原表(truncate table), 否則會出現多個相同的標識值的列!
2. 為NULL值的列
2.1 SqlBulkCopyOptions.KeepNulls 必須設置!否則會出現源數據的字段為NULL時, 復制過去卻成了默認值!
其它幾個選項的說明與分析:
Default 對所有選項使用默認值。
KeepIdentity 保留源標識值。如果未指定,則由目標分配標識值。
CheckConstraints 請在插入數據的同時檢查約束。默認情況下,不檢查約束。
TableLock 在批量復制操作期間獲取批量更新鎖。如果未指定,則使用行鎖。
KeepNulls 保留目標表中的空值,而不管默認值的設置如何。如果未指定,則空值將由默認值替換(如果適用)。
FireTriggers 指定后,會導致服務器為插入到數據庫中的行激發插入觸發器。 默認情況下, 是不激發觸發器的……
UseInternalTransaction 如果已指定,則每一批批量復制操作將在事務中發生。 在一個事務中執行,要么都成功,要么都不成功
Default 就沒有什么好說的了, 不要
KeepIdentity 和 KeepNulls 上面已有了, 不再分析。
CheckConstraints 不需要, 因為是現成的數據, 既然已在DB中, 必然是通過了約束檢查的。
TableLock 不需要, 因為復制時兩個庫都需要處於單連接狀態, 不可能有干擾。
FireTriggers 一般就不需要了吧, 畢竟只是復制數據, 而且是現成的數據……
UseInternalTransaction 關系也不大, 反正復制失敗會記錄到自定義的日志, 失敗了也知道, 重來一次就可以了。
下面是便於測試的代碼
SQL:
--1. 建數據來源表 IF EXISTS ( SELECT 1 FROM sysobjects WHERE id = OBJECT_ID(N'Table_1') AND OBJECTPROPERTY(id, N'IsUserTable') = 1 ) BEGIN DROP TABLE Table_1 END GO Create Table Table_1( ID INT, [NAME] VARCHAR(50) DEFAULT('xx') ) GO INSERT INTO Table_1 SELECT 1,'a' UNION SELECT 2,'b' UNION SELECT 3,'c' UNION SELECT 4,'d' UNION SELECT 5,'e' UNION SELECT 6,null --2. 建目標表 IF EXISTS ( SELECT 1 FROM sysobjects WHERE id = OBJECT_ID(N'Table_2') AND OBJECTPROPERTY(id, N'IsUserTable') = 1 ) BEGIN DROP TABLE Table_2 END GO Create Table Table_2( ID2 INT, [NAME2] VARCHAR(50) DEFAULT('xx') ) GO --復制時的對應關系 --Tabe_1 ==> Table_2 --ID ==> ID2 --[NAME] ==> [NAME2]
C# 控制台程序:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.SqlClient; using System.Collections; namespace SqlBulkCopyDemo { class Program { static void Main(string[] args) { string connString = System.Configuration.ConfigurationManager.AppSettings["DCString"]; SqlConnection ConnectionNew = new SqlConnection(connString); SqlConnection ConnectionOld = new SqlConnection(connString); bool ExportInfo = System.Configuration.ConfigurationManager.AppSettings["ExportInfo"].ToLower()=="true"; try { ConnectionNew.Open(); ConnectionOld.Open(); //1.在舊表中,用SqlDataReader讀取出信息 string SQL = "select * from Table_1"; SqlCommand cmd = new SqlCommand(SQL, ConnectionOld); cmd.CommandTimeout = 7200; SqlDataReader sdr = cmd.ExecuteReader(); //2.初始化SqlBulkCopy對象,用新的連接作為參數。 SqlBulkCopy bulkCopy = new SqlBulkCopy(ConnectionNew, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls, null); bulkCopy.BulkCopyTimeout = 7200; //3.寫對應關系。如舊表的People列的數據,對應新表Human列,那么就寫bulkCopy.ColumnMappings.Add("People","Human") //如果兩張表的結構一樣,那么對應關系就不用寫了。 //我是用哈希表存儲對應關系的,哈希表作為參數到傳入方法中,key的值用來存儲舊表的字段名,VALUE的值用來存儲新表的值 Hashtable ht = new Hashtable(); ht.Add("ID", "ID2"); ht.Add("NAME", "NAME2");// foreach (string str in ht.Keys) { bulkCopy.ColumnMappings.Add(str, ht[str].ToString()); } //4.設置目標表名 bulkCopy.DestinationTableName = "Table_2"; //額外,可不寫:設置一次性處理的行數。這個行數處理完后,會激發SqlRowsCopied()方法。默認為1 bulkCopy.NotifyAfter = 1; if (ExportInfo) { //額外,可不寫:設置激發的SqlRowsCopied()方法,這里為bulkCopy_SqlRowsCopied bulkCopy.SqlRowsCopied += new SqlRowsCopiedEventHandler(bulkCopy_SqlRowsCopied); } //OK,開始傳數據! DateTime dt = DateTime.Now; Console.WriteLine("開始時間:{0:yyyy-MM-dd HH:mm:ss,ms}", dt); bulkCopy.WriteToServer(sdr); DateTime dt2 = DateTime.Now; Console.WriteLine("結束時間:{0:yyyy-MM-dd HH:mm:ss,ms}", dt2); double time = dt2.Subtract(dt).TotalMilliseconds; Console.WriteLine("傳輸完畢!所用時間為:{0}(ms)", time); Console.Read(); } catch (Exception ex) { Console.Write(ex.Message); Console.Read(); } finally { ConnectionNew.Close(); ConnectionOld.Close(); } } //激發的方法寫在外頭 private static void bulkCopy_SqlRowsCopied(object sender, SqlRowsCopiedEventArgs e) { //執行的內容。 //這里有2個元素值得拿來用 //e.RowsCopied, //返回數值類型,表示當前已經復制的行數 //e.Abort, //用於賦值true or false,用於停止賦值的操作 Console.WriteLine("當前已復制的行數:" + e.RowsCopied); } } }
配置文件:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="DCString" value="Data Source=(local);Initial Catalog=db_Study;Persist Security Info=True;User ID=??;Password=??" /> <add key="ExportInfo" value="false" /> </appSettings> </configuration>