Database 板


LINE

原文恕删,谨简单整理您问题的重点: 1. 来源资料档的内容与汇入目的资料表的内容部分重复。 2. 由於每次汇入汇出的资料笔数有十万笔,「先删除後新增」的作法效率不彰。 3. 解决方案希望能在 SQL Server 与 Oracle 两种平台都能执行。 针对以上三点,我建议的解决方案是: 1. C# 程式读入文字档,利用 SqlBulkCopy 物件将资料整批汇入暂存资料表。 (SqlBulkCopy 的速度不输 bcp,而且,对象也不限 SQL Server) 2. 以 MERGE 指令,将暂存资料表合并到真正的目的资料表。 (SQL Server 与 Oracle 都支援 MERGE 指令) 有兴趣的网友,不妨一同试试以下这个 Lab: (我以 SQL Server 举例) 1. 在 SQL Server 建立 Lab 环境: create database BulkTestDB go use BulkTestDB go create table BulkTestTable ( id int primary key, aDate date, data varchar(15) ) go select * into BulkTestTempTable from BulkTestTable where 1 = 0 go 2. 利用 C# Express 新增一个 Windows 专案 3. 放置一个按钮,名称: btnCreateDataFiles,其 Click 事件如下: using System.IO; using System.Data.SqlClient; ... // 在 C:\temp 建立两个文字档,等一下要汇入这两个文字档 private void btnCreateDataFiles_Click(object sender, EventArgs e) { int iRowCount = 250000; // 实验的笔数请自己调整 System.IO.Directory.CreateDirectory(@"c:\temp"); DateTime dNow = DateTime.Now; StreamWriter w = new StreamWriter(@"c:\temp\dataSource1.txt", false); for (int iRow = 1; iRow <= iRowCount; iRow += 2) { // format: #, Date, data# w.WriteLine(string.Format("{0},{1},data{2}", iRow, dNow.AddSeconds(iRow).ToString("yyyy-MM-dd"), iRow)); } w.Close(); w = new StreamWriter(@"c:\temp\dataSource2.txt", false); for (int iRow = 1; iRow <= iRowCount; iRow++) { // format: #, Date, DATA# w.WriteLine(string.Format("{0},{1},DATA{2}", iRow, dNow.AddSeconds(iRow).ToString("yyyy-MM-dd"), iRow)); } w.Close(); btnCreateDataFiles.Text = "Done"; } 4. 放置一个按钮,名称: btnInsertOneByOne,Click事件及相关函式如下: (汇入 dataSource1.txt,这个方法非常慢...) // 建立并传回 Connection 物件 SqlConnection GetConnection() { string s = "Server=.\\SQLExpress;Database=BulkTestDB;Integrated Security=true"; SqlConnection Result = new SqlConnection(s); Result.Open(); return Result; } // 这个方法很慢,非常慢 _.,-zZ private void btnInsertOneByOne_Click(object sender, EventArgs e) { SqlConnection cn = GetConnection(); SqlCommand cmd = new SqlCommand("Insert into BulkTestTable values (@id, @aDate, @data)", cn); cmd.Parameters.Add("@id", SqlDbType.Int); cmd.Parameters.Add("@aDate", SqlDbType.Date); cmd.Parameters.Add("@data", SqlDbType.VarChar, 15); StreamReader r = new StreamReader(@"c:\temp\dataSource1.txt"); while (!r.EndOfStream) { string[] Data = r.ReadLine().Split(','); for (int iCol = 0; iCol < Data.Length; iCol++) cmd.Parameters[iCol].Value = Data[iCol]; cmd.ExecuteNonQuery(); } r.Close(); cn.Close(); btnInsertOneByOne.Text = "Done"; } 5. 放置一个按钮,名称: btnBulkCopyToTempTable,其 Click 事件: (将 dataSource2.txt 以 SqlBulkCopy 整批汇入到暂存资料表) (dataSource2.txt 比 dataSource1.txt 大上一倍,但汇入速度至少快二十倍) private void btnBulkCopyToTempTable_Click(object sender, EventArgs e) { SqlConnection cn = GetConnection(); SqlBulkCopy sbc = new SqlBulkCopy(cn); // 1. 建立SqlBulkCopy物件 sbc.DestinationTableName = "BulkTestTempTable"; // 2. 指定目的资料表 DataTable dt = new DataTable(); dt.Columns.Add("id", System.Type.GetType("System.Int32")); dt.Columns.Add("aDate", System.Type.GetType("System.DateTime")); dt.Columns.Add("data", System.Type.GetType("System.String")); StreamReader r = new StreamReader(@"c:\temp\dataSource2.txt"); while (!r.EndOfStream) { string[] Data = r.ReadLine().Split(','); dt.Rows.Add(Data); } r.Close(); sbc.WriteToServer(dt); // 3.整批写到资料库伺服器 sbc.Close(); cn.Close(); btnBulkCopyToTempTable.Text = "Done"; } 6. 放置一个按钮,名称: btnMerge,其 Click 事件如下: private void btnMerge_Click(object sender, EventArgs e) { SqlConnection cn = GetConnection(); string sMergeCommand = "merge BulkTestTable as dest" + " using (select * from BulkTestTempTable) as source" + " on (dest.id = source.id)" + " when matched then " + " update set dest.data = source.data" + " when not matched by target then " + " insert (id, aDate, data) values (source.id, source.aDate, source.data);"; SqlCommand cmd = new SqlCommand(sMergeCommand, cn); cmd.ExecuteNonQuery(); cn.Close(); btnMerge.Text = "Done"; } 以上,请依序执行上述按钮。 关於下列 MERGE 叙述,速度的关键在於 on 比对条件,如果没有编索引,速度快不 起来,详情请参考: http://ppt.cc/L84i merge BulkTestTable as dest using (select * from BulkTestTempTable) as source on (dest.id = source.id) when matched then update set dest.data = source.data when not matched by target then insert (id, aDate, data) values (source.id, source.aDate, source.data); 最後,SQL Server 的 MERGE 叙述也可以直接读入文字档,不一定要透过 C# 程式先 将资料读入暂存资料表,详细作法在上述 http://ppt.cc/L84i 文件中也有提到。预祝 顺利成功! ^_^ --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 118.170.133.215 ※ 编辑: TeemingVoid 来自: 118.170.133.215 (08/13 21:38)
1F:推 soon:太感人了Q_Q 不仅整理了我杂乱的需求还提供范例,感谢您! 08/14 12:44







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Gossiping站内搜寻

TOP