2013-05-28 77 views
2

我想編寫一個Oracle存儲過程來更新數據庫上的一個表,其中有一種方法可以給過程提供(或不給予)columname參數意味着「不更新此列」。這跟傳遞值,NULL或不更新此列到Oracle表更新存儲過程?

 
update tablename set 
     columnname = nvl(p_columnname, columnname), 
     ... 
where key  = p_key 

如果你這樣做,你不能空出列。我希望能夠將列空出來。如果Oracle支持無類型關鍵字UNKNOWN,那麼可以說p_columname varchar2:= UNKNOWN,並在自定義函數中測試是否省略該參數。但是如果沒有這個功能,它會定義一些神奇的值,意思是「不更新該列」,每種數據類型都有一個值,這樣我就不會在比較不兼容的數據類型時出錯。

這看起來像是一個常見問題(一個存儲過程處理對錶的所有更新,而不需要先讀後選擇不改變的列)。當然有人會想出一個最佳實踐來處理它。無論如何希望如此。提前致謝。

+3

就我個人而言,我會使用不同的存儲過程*每個事務*,以及該用例所需的確切SQL(當然,如果需要,使用助手存儲過程)。我發現「表」存儲過程不是很有用(我必須承認,我已經接觸過高劑量的http://asktom.oracle.com/) – gpeche

+0

我同意。我僅在需要時才使用表存儲過程,或者(a)因爲更新非常棘手,或者(b)我的客戶有一個標準規定它們的使用。無論哪種方式,實現表存儲過程的原因是將處理邏輯移動到數據庫,如果調用者必須將一堆列設置爲null或其他似是而非的值,那麼這是處理邏輯已經從數據庫流失的標誌。我建議每個交易都有一個不同的程序,並將它們放入一個包中。如果你願意,你可以給它們相同的名字 - Oracle支持重載。 –

+0

非常感謝您的回覆。不幸的是,我不確定哪些列會更新。客戶會這樣做,並向我發送只包含已更改列的最小XML。爲每個可能的列組合創建一個存儲過程將是一次組合爆炸。 – WebManWalking

回答

1

在一方面提供完美集中的更新和另一方面更新所有內容之間的易用性之間存在一個平衡點。它們都可能會對性能產生負面影響。

當你更新每一列時,顯然會增加重做,增加撤銷,重做日誌上的更高負載,更長的等待日誌文件同步,多餘的外鍵值檢查的可能性等等。由開發人員在故障排除和重新開發中丟失。

但是另一方面,如果每個更新都完全集中,那麼共享池中的一個更新語句可能會有五個,十個,二十個等 - 但是可以有多種更改組合。這本身就是一件壞事,可能會導致硬解析的增加,並在稍後進行故障排除。中間層可能會嘗試識別更常見的更新類型(例如更改電話號碼,更新訂單狀態等),併爲這些更新提供專門更新,併發送其他更新(希望只有少數)到一般更新。

通過檢查要格外小心,你可能會考慮記錄每60利用總體更新,看看到底是什麼改變,並嘗試拿起任何意外常見的組合(或使用了錯誤的更新API開發人員):

extract(second from systimestamp) < 1 

...什麼的。

+0

非常感謝您的回覆。不幸的是,沒有任何模式要更新的列。我保留傳入XML的審計線索,並可以構建XML標記(映射到數據庫列)的相關矩陣。然而,在程序中檢測「不更新此列」條件確實會更好。 – WebManWalking

+0

您打算處理多少個獨特的更新組合?您認爲? –

0

如果要有條件地設置一欄,你可以這樣做使用case語句:

update table 
set column = case 
        when <your condition here> then 
        column 
        else 
        parameter 
       end 

這臺當你的「無更新條件」被滿足柱往自己(即沒有更新)。你需要決定你需要什麼參數來識別這個。通過nvl提供的優點是,如果需要,可以將列設置爲null。