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

如何高效的将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的情况是否可以优化?除了我代码中的例子,我实在想不出其他办法。

  1. usingSystem;
  2. usingSystem.Data;
  3. usingSystem.Text;
  4. usingSystem.Windows.Forms;
  5. usingMicrosoft.Office.Interop.Excel;
  6. usingSystem.Data.OleDb;
  7. //引用-com-microsoftexcelobjects11.0
  8. namespaceWindowsApplication5
  9. {
  10. publicpartialclassForm1:Form
  11. {
  12. publicForm1()
  13. {
  14. InitializeComponent();
  15. }
  16. ///<SUMMARY>
  17. ///excel导入到oracle
  18. ///</SUMMARY>
  19. ///<PARAMname="excelFile">文件名</PARAM>
  20. ///<PARAMname="sheetName">sheet名</PARAM>
  21. ///<PARAMname="sqlplusString">oracle命令sqlplus连接串</PARAM>
  22. publicvoidTransferData(stringexcelFile,stringsheetName,stringsqlplusString)
  23. {
  24. stringstrTempDir=System.IO.Path.GetDirectoryName(excelFile);
  25. stringstrFileName=System.IO.Path.GetFileNameWithoutExtension(excelFile);
  26. stringstrCsvPath=strTempDir+"//"+strFileName+".csv";
  27. stringstrCtlPath=strTempDir+"//"+strFileName+".Ctl";
  28. stringstrSqlPath=strTempDir+"//"+strFileName+".Sql";
  29. if(System.IO.File.Exists(strCsvPath))
  30. System.IO.File.Delete(strCsvPath);
  31. //获取excel对象
  32. Microsoft.Office.Interop.Excel.ApplicationObjExcel=newMicrosoft.Office.Interop.Excel.Application();
  33. Microsoft.Office.Interop.Excel.WorkbookObjWorkBook;
  34. Microsoft.Office.Interop.Excel.WorksheetObjWorkSheet=null;
  35. 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);
  36. foreach(Microsoft.Office.Interop.Excel.WorksheetsheetinObjWorkBook.Sheets)
  37. {
  38. if(sheet.Name.ToLower()==sheetName.ToLower())
  39. {
  40. ObjWorkSheet=sheet;
  41. break;
  42. }
  43. }
  44. if(ObjWorkSheet==null)thrownewException(string.Format("{0}notfound!!",sheetName));
  45. //保存为csv临时文件
  46. ObjWorkSheet.SaveAs(strCsvPath,Microsoft.Office.Interop.Excel.XlFileFormat.xlCSV,Type.Missing,Type.Missing,false,false,false,Type.Missing,Type.Missing,false);
  47. ObjWorkBook.Close(false,Type.Missing,Type.Missing);
  48. ObjExcel.Quit();
  49. //读取csv文件,需要将表头去掉,并且将最后一列为null的字段处理为显示的null,否则oracle不会识别,这个步骤有没有好的替换方法?
  50. System.IO.StreamReaderreader=newSystem.IO.StreamReader(strCsvPath,Encoding.GetEncoding("gb2312"));
  51. stringstrAll=reader.ReadToEnd();
  52. reader.Close();
  53. stringstrData=strAll.Substring(strAll.IndexOf("/r/n")+2).Replace(",/r/n",",Null");
  54. byte[]bytes=System.Text.Encoding.Default.GetBytes(strData);
  55. System.IO.Streamms=System.IO.File.Create(strCsvPath);
  56. ms.Write(bytes,0,bytes.Length);
  57. ms.Close();
  58. //获取excel表结构
  59. stringstrConn="Provider=Microsoft.Jet.OLEDB.4.0;"+"DataSource="+excelFile+";"+"ExtendedProperties=Excel8.0;";
  60. OleDbConnectionconn=newOleDbConnection(strConn);
  61. conn.Open();
  62. System.Data.DataTabletable=conn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Columns,
  63. newobject[]{null,null,sheetName+"$",null});
  64. //生成sqlldr用到的控制文件,文件结构参考sql*loader功能,本示例已逗号分隔csv,数据带逗号的用引号括起来。
  65. stringstrControl="loaddata/r/ninfile&apos;{0}&apos;/r/nappendintotable{1}/r/n"+   
  66.   "FIELDSTERMINATEDBY&apos;,&apos;OPTIONALLYENCLOSEDBY&apos;/"&apos;/r/n(";  
  67. strControl=string.Format(strControl,strCsvPath,sheetName);
  68. foreach(System.Data.DataRowdrowColumnsintable.Select("1=1","Ordinal_Position"))
  69. {
  70. strControl+=drowColumns["Column_Name"].ToString()+",";
  71. }
  72. strControl=strControl.Substring(0,strControl.Length-1)+")";
  73. bytes=System.Text.Encoding.Default.GetBytes(strControl);
  74. ms=System.IO.File.Create(strCtlPath);
  75. ms.Write(bytes,0,bytes.Length);
  76. ms.Close();
  77. //生成初始化oracle表结构的文件
  78. stringstrSql=@"droptable{0};          
  79.   createtable{0} 
  80.   (";
  81. strSql=string.Format(strSql,sheetName);
  82. foreach(System.Data.DataRowdrowColumnsintable.Select("1=1","Ordinal_Position"))
  83. {
  84. strSql+=drowColumns["Column_Name"].ToString()+"varchar2(255),";
  85. }
  86. strSql=strSql.Substring(0,strSql.Length-1)+");/r/nexit;";
  87. bytes=System.Text.Encoding.Default.GetBytes(strSql);
  88. ms=System.IO.File.Create(strSqlPath);
  89. ms.Write(bytes,0,bytes.Length);
  90. ms.Close();
  91. //运行sqlplus,初始化表
  92. System.Diagnostics.Processp=newSystem.Diagnostics.Process();
  93. p.StartInfo=newSystem.Diagnostics.ProcessStartInfo();
  94. p.StartInfo.FileName="sqlplus";
  95. p.StartInfo.Arguments=string.Format("{0}@{1}",sqlplusString,strSqlPath);
  96. p.StartInfo.WindowStyle=System.Diagnostics.ProcessWindowStyle.Hidden;
  97. p.StartInfo.UseShellExecute=false;
  98. p.StartInfo.CreateNoWindow=true;
  99. p.Start();
  100. p.WaitForExit();
  101. //运行sqlldr,导入数据
  102. p=newSystem.Diagnostics.Process();
  103. p.StartInfo=newSystem.Diagnostics.ProcessStartInfo();
  104. p.StartInfo.FileName="sqlldr";
  105. p.StartInfo.Arguments=string.Format("{0}{1}",sqlplusString,strCtlPath);
  106. p.StartInfo.WindowStyle=System.Diagnostics.ProcessWindowStyle.Hidden;
  107. p.StartInfo.RedirectStandardOutput=true;
  108. p.StartInfo.UseShellExecute=false;
  109. p.StartInfo.CreateNoWindow=true;
  110. p.Start();
  111. System.IO.StreamReaderr=p.StandardOutput;//截取输出流
  112. stringline=r.ReadLine();//每次读取一行
  113. textBox3.Text+=line+"/r/n";
  114. while(!r.EndOfStream)
  115. {
  116. line=r.ReadLine();
  117. textBox3.Text+=line+"/r/n";
  118. textBox3.Update();
  119. }
  120. p.WaitForExit();
  121. //可以自行解决掉临时文件csv,ctl和sql,代码略去
  122. }
  123. privatevoidbutton1_Click(objectsender,EventArgse)
  124. {
  125. TransferData(@"D:/test.xls","Sheet1","username/password@servicename");
  126. }
  127. }
  128. }

你可能感兴趣的:(oracle)