比使用 Merge 語句更新表的列更好的方法
我有一個這種結構的表
Table1(Cust_No Varchar2(50), First_Name Varchar2(50), Last_Name Varchar2(50), Error_Code Number(1) , Error_Desc Varchar2(50))
還有另一個具有這種結構的表
Table2(Cust_No Varchar2(50), Customer_FirstName Varchar2(50), Customer_LastName Varchar2(50) )
想像一下 Column
Cust_No
fromTable1
有數據。我的意思是這個欄位中有一些 Cust_No 的數據。我需要Update
根據該列和該列的表的其他列,Cust_No
並為每個客戶編號Table2
查找。First_Name and Last_Name
到目前為止我寫的是這樣的:-- FIND CUSTOMER'S FIRST AND LAST NAME MERGE INTO (SELECT * FROM REQUEST R WHERE R.IS_CHECKED IS NULL) R USING VMI_DIMCUSTOMER V ON (V.CUSTOMER_NUM = R.CUST_NO) WHEN MATCHED THEN UPDATE SET R.FIRST_NAME = V.CUST_FIRST_NAME, R.LAST_NAME = V.CUST_LAST_NAME, R.ERROR_CODE = 0, R.IS_CHECKED = 1; COMMIT; -- CUSTOMERS NOT FOUND UPDATE /*+ PARALLEL(4) */ REQUEST T SET T.FIRST_NAME = '--', T.LAST_NAME = '--', T.ERROR_CODE = 2, T.ERROR_DESC = 'Customer Not Found', T.IS_CHECKED = 0 WHERE T.FIRST_NAME IS NULL; COMMIT;
我在這個查詢中所做的是首先,我使用
Merge
語句來查找客戶的名字和姓氏,並Is_Checked
在客戶有名字和姓氏時將列更新為 1。在第二部分中,我將更新與Table2
.我想知道在性能方面是否有更好的方法來編寫這個查詢。
如果我明白你在那裡做什麼(我可能不是 100% .. ).. 看來你正在嘗試更新 REQUEST 表,使用另一個 VMI_DIMCUSTOMER 表作為“輸入”.. 但前提是存在記錄。如果 VMI_DIMCUSTOMER 表中沒有記錄,對於 REQUEST 中的給定記錄,您希望使用“找不到客戶”消息標記 REQUEST 中的記錄,並將名字/姓氏設置為 ‘–’ 並將錯誤程式碼設置為 2 和is_checked 為 0。
如果找到記錄,而不是填充名稱,is_checked 設置為 1,錯誤程式碼設置為 0。
這可以在單個 sql 中完成。我以前使用過這種方法。基本思想是,忘記更新、合併等,只需編寫一個返回您真正想要的 END STATE 的 SELECT 語句。
如果我理解正確的話。你想要這樣的東西:
SELECT CASE WHEN v.cust_first_name IS NULL THEN '--' ELSE r.first_name END first_name, CASE WHEN v.cust_first_name IS NULL THEN '--' ELSE r.last_name END last_name, CASE WHEN v.cust_first_name IS NULL THEN 2 ELSE 0 END error_code, CASE WHEN v.cust_first_name IS NULL THEN 0 ELSE 1 END is_checked, CASE WHEN v.cust_first_name IS NULL THEN 'Customer Not Found' ELSE NULL END error_desc FROM request r LEFT OUTER JOIN vmi_dimcustomer v ON v.cust_first_name = r.first_name and v.cust_last_name = r.last_name WHERE r.error_code = 0 AND r.is_checked = 1 /
通過執行外連接,我們將在 REQUEST 中包含所有行,即使我們在 VMI_DIMCUSTOMER 中找不到它們。我們檢查 VMI_DIMCUSTOMER 中的 CUST_FIRST_NAME 是否為空(如果您有 CUST_NO 列,則可以改為檢查 .. 但您顯示的表結構與您使用的不同.. 所以不確定)。
並使用 CASE 為每一行提取/設置您想要/需要的任何值,具體取決於您是否在 VMI_DIMCUSTOMER 中找到它。
一旦你完成了“最終結果集”查詢(並且很容易測試執行以驗證.. ;))
將其插入合併很簡單……首先,將 rowid 添加到查詢中,以便更容易挑選出行……然後插入一個簡單的 MERGE :
MERGE INTO request old USING ( SELECT r.rowid rid, CASE WHEN v.cust_first_name IS NULL THEN '--' ELSE r.first_name END first_name, CASE WHEN v.cust_first_name IS NULL THEN '--' ELSE r.last_name END last_name, CASE WHEN v.cust_first_name IS NULL THEN 2 ELSE 0 END error_code, CASE WHEN v.cust_first_name IS NULL THEN 0 ELSE 1 END is_checked, CASE WHEN v.cust_first_name IS NULL THEN 'Customer Not Found' ELSE NULL END error_desc FROM request r LEFT OUTER JOIN vmi_dimcustomer v ON v.cust_first_name = r.first_name and v.cust_last_name = r.last_name WHERE r.error_code = 0 AND r.is_checked = 1 ) new ON ( new.rid = old.rowid ) WHEN MATCHED THEN UPDATE SET old.first_name = new.first_name, old.last_name = new.last_name, old.error_code = new.error_code, old.is_checked = new.is_checked, old.error_desc = new.error_desc /
viola .. 1 sql,它會根據是否在另一個表中找到它們來設置標誌.. ;)
如果它不能完全按照您的需要工作,請更詳細地說明您的要求.. 修改合併以滿足您的需要應該不難。