2016-06-06 110 views
4

當爲我的sql動態生成WHERE子句時,我喜歡將WHERE '1' = '1'硬編碼到sql中,因此我不必跟蹤是否要爲每個子句添加AND。這在許多地方都有很好的記錄,例如stackoverflow question更新相當於WHERE'1'='1'

是否存在一個用於動態生成UPDATE語句的SET子句的等效模式?我寧願不跟蹤是否需要預先輸入逗號。如果沒有任何通用的解決方案,這將用於通過jdbc與oracle數據庫進行交互。

編輯 對於我的特殊用例,我需要動態更改正在設置的列。因此,任何需要查詢包含所有列的解決方案都是不可行的。我們有一張20列以上的表格,但在任何時候只有3或4個表格會發生變化。我們運行了一些負載測試,發現實現性能目標的唯一方法就是發送需要更新的數據。現在我只是想寫出漂亮的代碼來實現這一點。爲了避免跟蹤列數爲附加逗號的目的

+3

簡短的回答是沒有。就我個人而言,我討厭「1 = 1」的東西,並且傾向於編寫智能邏輯,根據需要連接多少個表達式來知道是否預先加上','或者'和'。您可能想要觀察系統必須處理的解析負載 - 確保始終每次都使用相同順序生成SET子句,以最小化此問題。 –

回答

2

一種方式是始終分配所有可能的列,並通過一組控制變量來決定是否列應分配與否:

UPDATE MyTable 
SET 
    col1 = CASE ? WHEN 1 THEN ? ELSE col1 END 
, col2 = CASE ? WHEN 1 THEN ? ELSE col2 END 
, col3 = CASE ? WHEN 1 THEN ? ELSE col3 END 
WHERE 
    ... -- condition goes here 

奇數索引處的參數是您傳遞的標誌,指示必須設置相應的列。相應偶數索引處的參數是您要設置的值,如果您未設置相應的字段,則爲NULL

該方法使您需要傳遞的JDBC參數數量翻倍,但作爲回報,您將得到一個聲明,其中所有列的位置都是固定的,因此您可以準備並重用它,而不是動態構建它。

+1

如果底層Oracle數據庫有很多'UPDATE'觸發器,這會使事情複雜化,因爲在確定是否觸發觸發器時,Oracle不區分'UPDATE mytable SET mycolumn = mycolumn'和'UPDATE mytable SET mycolumn = mynewvalue'。 –

+0

+1這是一個很好的答案,很遺憾不符合我的用例。我用更多的標準更新了原始問題,抱歉不清楚。 – Josh

+0

@Josh「[我們]發現實現性能目標的唯一方法就是發送需要更新的數據。」您仍然只發送需要更新的數據,其餘列將爲NULL ,所以他們只需要很少的帶寬。能夠準備語句,而不是每次使用不同的SQL,都會爲您節省相當多的時間。 – dasblinkenlight

1

首先,如果沒有更改,最好不要執行查詢。

但是,如果你有,或做其他的方式是更昂貴的,通常你可以這樣做:

UPDATE 
    MY_TABLE 
SET 
    <if test="xx"> COL1='VAL1',</if> 
    ID=ID 
where 1=1 
    COL1 like 'VAL%'; 

隨着ID=ID作爲一個空操作。

請記住,這仍然會執行所有「副作用」的更新,如運行觸發器。

+0

單行更新永遠不會鎖定Postgres中的整個表。無論WHERE條件或哪些列被更新 –

+0

@a_horse_with_no_name感謝您的評論。它發生在甲骨文,並造成我一個嚴重的問題,所以我決定更新答案。 – Dariusz

+0

Oracle在執行'UPDATE'時也不會鎖定整個表格。 –