c#中高效的excel匯入oracle的方法

來源:互聯網
上載者:User

如何高效的將excel匯入到oracle?和前兩天的SqlBulkCopy 匯入到sqlserver對應,oracle也有自身的方法,只是稍微複雜些.
那就是使用oracle的sql*loader功能,而sqlldr只支援類似csv格式的資料,所以要自己把excel轉換一下。
實現步驟:
用com組件讀取excel-儲存為csv格式-處理最後一個欄位為null的情況和表頭-根據excel結構建表-產生sqlldr的控制檔案-用sqlldr命令匯入資料
這個效能雖然沒有sql的bcp快,但還是相當可觀的,在我機器上1萬多資料不到4秒,而且匯入處理程序代碼比較簡單,也同樣沒有迴圈拼接sql插入那麼難以維護。

這裡也提個問題:處理csv檔案的表頭和最後一個欄位為null的情況是否可以最佳化?除了我代碼中的例子,我實在想不出其他辦法。

 

using System;using System.Data;using System.Text;using System.Windows.Forms;using Microsoft.Office.Interop.Excel;using System.Data.OleDb;//引用-com-microsoft excel objects 11.0namespace WindowsApplication5{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }         ///         /// excel匯入到oracle        ///         /// 檔案名稱        /// sheet名        /// oracle命令sqlplus串連串        public void TransferData(string excelFile, string sheetName, string sqlplusString)        {            string strTempDir = System.IO.Path.GetDirectoryName(excelFile);            string strFileName = System.IO.Path.GetFileNameWithoutExtension(excelFile);            string strCsvPath = strTempDir +"//"+strFileName + ".csv";            string strCtlPath = strTempDir + "//" + strFileName + ".Ctl";            string strSqlPath = strTempDir + "//" + strFileName + ".Sql";            if (System.IO.File.Exists(strCsvPath))                System.IO.File.Delete(strCsvPath);            //擷取excel對象            Microsoft.Office.Interop.Excel.Application ObjExcel = new Microsoft.Office.Interop.Excel.Application();            Microsoft.Office.Interop.Excel.Workbook ObjWorkBook;            Microsoft.Office.Interop.Excel.Worksheet ObjWorkSheet = null;            ObjWorkBook = ObjExcel.Workbooks.Open(excelFile, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);            foreach (Microsoft.Office.Interop.Excel.Worksheet sheet in ObjWorkBook.Sheets)            {                if (sheet.Name.ToLower() == sheetName.ToLower())                {                    ObjWorkSheet = sheet;                    break;                }            }            if (ObjWorkSheet == null) throw new Exception(string.Format("{0} not found!!", sheetName));            //儲存為csv臨時檔案            ObjWorkSheet.SaveAs(strCsvPath, Microsoft.Office.Interop.Excel.XlFileFormat.xlCSV, Type.Missing, Type.Missing, false, false, false, Type.Missing, Type.Missing, false);            ObjWorkBook.Close(false, Type.Missing, Type.Missing);            ObjExcel.Quit();            //讀取csv檔案,需要將表頭去掉,並且將最後一列為null的欄位處理為顯示的null,否則oracle不會識別,這個步驟有沒有好的替換方法?            System.IO.StreamReader reader = new System.IO.StreamReader(strCsvPath,Encoding.GetEncoding("gb2312"));            string strAll = reader.ReadToEnd();            reader.Close();            string strData = strAll.Substring(strAll.IndexOf("/r/n") + 2).Replace(",/r/n",",Null");            byte[] bytes = System.Text.Encoding.Default.GetBytes(strData);            System.IO.Stream ms = System.IO.File.Create(strCsvPath);            ms.Write(bytes, 0, bytes.Length);            ms.Close();            //擷取excel表結構            string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + excelFile + ";" + "Extended Properties=Excel 8.0;";            OleDbConnection conn = new OleDbConnection(strConn);            conn.Open();            System.Data.DataTable table = conn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Columns,                new object[] { null, null, sheetName+"$", null });            //產生sqlldr用到的控制檔案,檔案結構參考sql*loader功能,本樣本已逗號分隔csv,資料帶逗號的用引號括起來。               string strControl =  "load data/r/ninfile '{0}' /r/nappend into table {1}/r/n"+                      "FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '/"'/r/n(";              strControl = string.Format(strControl, strCsvPath,sheetName);            foreach (System.Data.DataRow drowColumns in table.Select("1=1", "Ordinal_Position"))            {                strControl += drowColumns["Column_Name"].ToString() + ",";            }            strControl = strControl.Substring(0, strControl.Length - 1) + ")";            bytes=System.Text.Encoding.Default.GetBytes(strControl);            ms= System.IO.File.Create(strCtlPath);            ms.Write(bytes, 0, bytes.Length);            ms.Close();            //產生初始化oracle表結構的檔案            string strSql = @"drop table {0};                              create table {0}                   (";            strSql = string.Format(strSql, sheetName);            foreach (System.Data.DataRow drowColumns in table.Select("1=1", "Ordinal_Position"))            {                strSql += drowColumns["Column_Name"].ToString() + " varchar2(255),";            }            strSql = strSql.Substring(0, strSql.Length - 1) + ");/r/nexit;";            bytes = System.Text.Encoding.Default.GetBytes(strSql);            ms = System.IO.File.Create(strSqlPath);            ms.Write(bytes, 0, bytes.Length);            ms.Close();            //運行sqlplus,初始化表            System.Diagnostics.Process p = new System.Diagnostics.Process();            p.StartInfo = new System.Diagnostics.ProcessStartInfo();            p.StartInfo.FileName = "sqlplus";            p.StartInfo.Arguments = string.Format("{0} @{1}", sqlplusString, strSqlPath);            p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;            p.StartInfo.UseShellExecute = false;            p.StartInfo.CreateNoWindow = true;            p.Start();            p.WaitForExit();            //運行sqlldr,匯入資料            p = new System.Diagnostics.Process();            p.StartInfo = new System.Diagnostics.ProcessStartInfo();            p.StartInfo.FileName = "sqlldr";            p.StartInfo.Arguments = string.Format("{0} {1}", sqlplusString, strCtlPath);            p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;            p.StartInfo.RedirectStandardOutput = true;            p.StartInfo.UseShellExecute = false;            p.StartInfo.CreateNoWindow = true;            p.Start();            System.IO.StreamReader r = p.StandardOutput;//截取輸出資料流            string line = r.ReadLine();//每次讀取一行            textBox3.Text += line + "/r/n";            while (!r.EndOfStream)            {                line = r.ReadLine();                textBox3.Text += line + "/r/n";                textBox3.Update();            }            p.WaitForExit();            //可以自行解決掉臨時檔案csv,ctl和sql,代碼略去        }        private void button1_Click(object sender, EventArgs e)        {            TransferData(@"D:/test.xls", "Sheet1", "username/password@servicename");        }            }}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.