如何用SqlBulkCopy完成未知列數和列名的資料表的採集
1. 寫入表設定為101列, 第1列為批次,每寫入一批資料作為一批;
2. 寫入表中的除batch之外的列均為 nvarchar(max);
3. 寫入資料時要將來源表中的表頭存放到另一張表中, 便於以後的匯出。
A. 測試資料準備
--1. 資料來源表 IF OBJECT_ID('source_table') IS NOT NULL DROP TABLE source_table GO CREATE TABLE source_table ( school NVARCHAR(100), account VARCHAR(200), cnt_ct INT, createTime DATETIME ) GO INSERT INTO source_table SELECT '春蘭小學','liuming',25,'2005-10-23' union SELECT '春蘭大學','leaf',25,'2005-10-20' GO --2. 目標表 IF OBJECT_ID('target_table') IS NOT NULL DROP TABLE target_table GO CREATE TABLE target_table ( batch BIGINT, C1 NVARCHAR(MAX), C2 NVARCHAR(MAX), C3 NVARCHAR(MAX), C4 NVARCHAR(MAX), C5 NVARCHAR(MAX), C6 NVARCHAR(MAX), C7 NVARCHAR(MAX), C8 NVARCHAR(MAX), C9 NVARCHAR(MAX), C10 NVARCHAR(MAX) ) GO --3. 表頭表 IF OBJECT_ID('header_table') IS NOT NULL DROP TABLE header_table GO CREATE TABLE header_table ( id BIGINT IDENTITY(1,1), batch BIGINT, columnName NVARCHAR(MAX), columnIndex int ) GO
2. DBHelper: 見: 點選開啟連結
3. 測試控制檯程式:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.SqlClient; using System.Collections; using System.Data; using Common; namespace ConsoleApplication1 { class Program_6 { static void Main(string[] args) { SqlConnection ConnectionNew = new SqlConnection("Data Source=leaf-home\\sqlserver2005;Initial Catalog=Test;Persist Security Info=True;User ID=??;Password=??"); SqlConnection ConnectionOld = new SqlConnection("Data Source=leaf-home\\sqlserver2005;Initial Catalog=Test;Persist Security Info=True;User ID=??;Password=??"); try { ConnectionNew.Open(); ConnectionOld.Open(); //1.在舊錶中,用SqlDataAdapter讀取出資訊 string SQL = "select school 學校,account 賬號,cnt_ct 簡訊量, createTime 建立日期 from source_table"; DataTable dt = Common.DBHelper.GetDataTableBySql(SQL); //資料來源表 DataTable dt_clone = dt.Clone(); //複製表, 用於加多一列, 並將其它列改為String型別 long batch = 3; DataColumn dcBatch = new DataColumn("batch"); dcBatch.DataType = typeof(long);// Type.GetType("System.Int64"); dt_clone.Columns.Add(dcBatch); dcBatch.SetOrdinal(0); //設定為第1列 非常重要 for (int i = 1; i < dt.Columns.Count; i++) { dt_clone.Columns[i].DataType = Type.GetType("System.String"); } foreach (DataRow dr in dt.Rows) { DataRow dr_clone = dt_clone.NewRow(); foreach (DataColumn dc in dt.Columns) { dr_clone[dc.ColumnName] = dr[dc.ColumnName]; } dr_clone[0] = batch; dt_clone.Rows.Add(dr_clone); } //將表頭存入表頭表中, 方便以後匯出時使用 int dcIdx = 1; foreach (DataColumn dc in dt.Columns) { SqlParameter[] spArr = new SqlParameter[]{ new SqlParameter("columnName", dc.ColumnName), new SqlParameter("batch",Convert.ToInt64(batch)).SetDbType(DbType.Int64), new SqlParameter("columnIndex",dcIdx++)}; string sql = @" if not exists(select 1 from header_table where
[email protected] and [email protected]) begin insert into header_table (columnName,batch,columnIndex) select @columnName,@batch,@columnIndex end "; Common.DBHelper.ExecuteNonQuery(sql, spArr); } //2.初始化SqlBulkCopy物件,用新的連線作為引數。 SqlBulkCopy bulkCopy = new SqlBulkCopy(ConnectionNew); //3.寫對應關係。如舊錶的People列的資料,對應新表Human列,那麼就寫bulkCopy.ColumnMappings.Add("People","Human") //如果兩張表的結構一樣,那麼對應關係就不用寫了。 //我是用雜湊表儲存對應關係的,雜湊表作為引數到傳入方法中,key的值用來儲存舊錶的欄位名,VALUE的值用來儲存新表的值 Hashtable ht = new Hashtable(); ht.Add("batch", "batch"); int j = 1; foreach (DataColumn dc in dt.Columns) { ht.Add(dc.ColumnName, "C" + (j++).ToString()); } foreach (string str in ht.Keys) { bulkCopy.ColumnMappings.Add(str, ht[str].ToString()); } //4.設定目標表名 bulkCopy.DestinationTableName = "target_table"; //額外,可不寫:設定一次性處理的行數。這個行數處理完後,會激發SqlRowsCopied()方法。預設為1 bulkCopy.NotifyAfter = 1; //額外,可不寫:設定激發的SqlRowsCopied()方法,這裡為bulkCopy_SqlRowsCopied bulkCopy.SqlRowsCopied += new SqlRowsCopiedEventHandler(bulkCopy_SqlRowsCopied); //OK,開始傳資料! bulkCopy.WriteToServer(dt_clone); Console.Write("傳輸完畢!"); 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); } } }
將上面的程式碼 batch 改為3(4個欄位), 4 (3個欄位), 執行兩次後結果如下:
很明顯, 在任意變化的情況下, 為我們實現了資料的轉移。
當然, 實際的資料採集過程, 可能還會複雜一些:比如同一批資料會有多次傳入。不過大體的思路可以定下來的了。
相關推薦
如何用SqlBulkCopy完成未知列數和列名的資料表的採集
SqlBulkCopy 很簡單也很好用, 但關鍵是當資料來源表非常靈活而多變時(事先不知道有多少列,也不知道每1列的列名), 如何來做這件事呢? 1. 寫入表設定為101列, 第1列為批次,每寫入一批資料作為一批; 2. 寫入表中的除batch之外的列均為 nvarcha
MySQL--修改資料表6:修改列定義和更名資料表
修改列定義和更名資料表把某一列移動到指定位置:ALTER TABLE users2 MODIFY id SMALLINT UNSIGNED NOT NULL FIRST; // 末尾也可加 (AFTER 列名) 放在某一列之後修改某一列的定義型別:ALTER TABLE us
Java獲得數據庫查詢結果的列數和行數,打印查詢結果
rman execute .get name 數據庫查詢 隨筆 while cti etc Java連接數據庫及簡單操作見我以前的一篇隨筆:http://www.cnblogs.com/meitian/p/5036332.html 一、獲取查詢結果的行數和列數 查詢結果
子類對父類的調用,主要是參數和方法調用
繼承 bsp pri load china 類的方法 調用父類 class sub #子類調用父類的方法 class Vehichle: Country=‘china‘ #名字=‘ales‘不好這樣 def __init__(self,name,s
深入淺出SQL Server 2008 分區函數和分區表
準備 引用 數據類型 發布 回復 不同 con 否則 stc http://www.cnblogs.com/zhijianliutang/archive/2012/10/28/2743722.html 我們數據量比較大的時候,我們需要將大型表拆分為多個較小的表,則
c++基礎語法之構造函數和初始化表
沒有 參數表 編譯器 ima http 構造函數 struct 轉換 顯示 筆者剛系統的重學了c++的語法,看到構造函數和初始化表這塊,發現這塊語法有點復雜且很雜,怕以後忘記,於是寫下此篇,以後回憶之用。 c++構造函數 3、構造函數(constructor
最快速度檢視windows系統 IIS 併發連線數和共享資料夾最大連線數的方法
windows系統 版本分伺服器版和家用版/企業版,比如 windows 7 是家用版/企業版,對應windows 2008/2008R2就是伺服器版。 家用版/企業版的共享資料夾連線和IIS都有最大限制,當同時訪 問人數過多,會導致其他人連不上目標機器。 於
單元二:建立和維護資料表
1、 一個關係由一個二維表表示 2、 二維表中的每一列稱為關係的一個屬性,即欄位 3、 二維表中的每一行的所有資料稱為一個元組,相當一個記錄,代表一個實體 4、 能唯一標識一個元組的一個或若干個屬性的集合稱為
mysql約束和修改資料表
FOREIGN KEY(外來鍵約束)要求: 1.父表子表必須使用相同的儲存引擎,而且禁止使用臨時表。 2.資料表的儲存引擎只能為INNODB. 3.外來鍵列於參照列必須具有相似的資料型別。數字長度和是否有符號位必須相同; 字元的長度可以不同。 4.外來鍵列和參照列必須建立索
MySQL 約束和修改資料表
1. FOREIGN KEY(外來鍵約束):保持資料的一致性,完整性。實現資料表的一對一,一對多的關係。 a) 父表(子表所參照的表)和子表(具有外來鍵列的表)必須使用相同的儲存引擎,
棧和隊列----用遞歸函數和棧的操作實現逆序一個棧
color return -- 並且 壓入 但是 遞歸 tel 結構 用遞歸函數和棧的操作實現逆序一個棧 一個棧依次壓入1、2、3、4、5,那麽從棧頂到棧底分別為5、4、3、2、1,將這個棧轉置後,從棧頂到棧底為1、2、3、4、5,也就是實現棧中元素的逆序,但是只能
算法:用兩個棧來實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素為int類型。《劍指offer》
pack 代碼 exception 隊列 imp scrip 入棧 return tro 算法:用兩個棧來實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素為int類型。《劍指offer》 利用棧來進行操作,代碼註釋寫的比較清楚:首先判斷兩個棧是否是空的:
題目描述 在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
這樣的 -i 一個 整數 描述 輸入 遞增 lse i+1 題目描述 在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。 1
python:用Redis完成發布和訂閱數據
sage host cal ins ESS div 安裝 def lis 安裝: pip install redis 發布文件: # coding:utf-8 import redis import json class RedisHelper():
面試題9-用兩個棧來實現一個隊列,完成隊列的Push和Pop操作
ati import str highlight print row pty 用兩個棧 div 題目 用兩個棧來實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素為int類型。 思路: 一個棧壓入元素,而另一個棧作為緩沖,將棧1的元素出棧後壓入棧2中
用VBA得到EXCEL表格中的行數和列數
方法3: ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Column 缺點:在工作表進行對刪除或清除操作時也會變得比實際情況大。方法
用C語言中的函式列印乘法口訣表,行數和列數可以任意輸入
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> void print_table(int line) { int i = 0;
exit庫函數和_exit系統調用對標準輸出的影響
eno 標準 代碼 for sizeof pan type lob int #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <stdli
數組、鏈表、堆棧和隊列
數組 經典 clas 刪除 概念 連續 con 一個 這樣的 鏈表,隊列,堆棧的區別1、棧是個有底的口袋,像襪子。隊列是沒底的口袋,像通心粉。所以:棧的特點是先進後出,隊列的特點是先進先出。2、主要區別是適用的地方不一樣, 鏈表實際上可以認為是一種數據的物理組織形式
js new一個函數和直接調用函數的差別
.get new javascrip 引用類型 類型 彈出 color pos 不同 用new和調用一個函數的差別:假設函數返回值是一個值類型(Number、String、Boolen)時,new函數將會返回這個函數的實例對象。而假設這個函數的返回值是一個引用類型(