2013-02-06 139 views
0

我正在構建一個與Oracle 11g數據庫交談的.NET應用程序。我試圖從第三方提供的Excel文件中提取數據並插入(UPDATE記錄是否存在,INSERT如果不存在),但是在性能方面存在一些問題。來自外部數據源的Oracle MERGE

這些Excel文件將取代資費代碼和說明,因此每個文件中有幾千條記錄。

| Tariff |  Description  | 
|----------------------------------------| 
| 1234567890 | 'Sample description here' | 

我做了批量插入一些研究,甚至還寫道,在應用程序打開一個交易功能,執行一堆UPDATEINSERT語句,然後提交。不幸的是,這需要很長時間,並延長了應用程序和數據庫之間的會話。

public void UpsertMultipleRecords(string[] updates, string[] inserts) { 
    OleDbConnection conn = new OleDbConnection("connection string here"); 
    conn.Open(); 
    OleDbTransaction trans = conn.BeginTransaction(); 
    try { 
     for (int i = 0; i < updates.Length; i++) { 
      OleDbCommand cmd = new OleDbCommand(updates[i], conn); 
      cmd.Transaction = trans; 
      int count = cmd.ExecuteNonQuery(); 
      if (count < 1) { 
       cmd = new OleDbCommand(inserts[i], conn); 
       cmd.Transaction = trans; 
      } 
     } 
     trans.Commit(); 
    } catch (OleDbException ex) { 
     trans.Rollback(); 
    } finally { 
     conn.Close(); 
    } 
} 

我發現通過向湯姆說做這樣的事情的一種有效的方法是使用Oracle MERGE聲明,在9i中實現的。據我所知,這隻能使用Oracle中的兩個現有表。我嘗試過,但不瞭解臨時表,或者如果這是可能的。如果我在MERGE上創建了一個只包含我的數據的新表,我仍需要一種可靠的批量插入方式。

回答

0

我通常上傳我的文件以合併的方式是首先插入一個加載表與sql*loader,然後從加載表執行合併語句到目標表中。

臨時表只會在會話期間保留它的內容。我期望sql * loader在完成時結束會話,所以最好使用在合併後截斷的普通表。

merge into target_table t 
using load_table l on (t.key = l.key) -- brackets are mandatory 
when matched then update 
set t.col = l.col 
, t.col2 = l.col2 
, t.col3 = l.col3 
when not matched then insert 
(t.key, t.col, t.col2, t.col3) 
values 
(l.key, l.col, l.col2, l.col3) 
+0

一個問題:我將不得不從Web應用程序運行sql * loader以便重複使用它。這可能嗎? – tedski

+0

它可以從命令行運行,但Web服務器也應該是我猜測的數據庫服務器。不是一個好習慣。 可能更適合使用.NET批量插入。提示:如果在BEGIN ... END中有很多插入語句,正文中,Oracle會將其視爲單個語句並僅解析一次。快得多。 – winkbrace

+0

不錯的建議。我最終使用這篇文章進行批量插入:http://dotnetslackers.com/articles/ado_net/BulkOperationsUsingOracleDataProviderForNETODPNET.aspx 我創建了一個表來保存數據並使用了你的'MERGE'語句。它工作得很好。謝謝! – tedski