2015-10-07 35 views
1

我有這個選擇查詢返回簡單的表 - 見下文。多連接'gotohell'更新

我花了一整天的時間試圖編寫一個更新聲明,當EQLOC爲NULL或與HOOKNO不一樣時,它應該用HOOKNO更新......但是我失敗了。

請幫忙。

SELECT ho.HOOK_OFFICE_LETTER || LPAD(khc.HOOK_NO, 5, '0') as hookno, eq.location_description as eqloc 
FROM KEY_HOOK_CURRENT khc 
    INNER JOIN KEY_HOLDING kho    ON khc.KEY_HOLDINGOID = kho.KEY_HOLDINGOID 
    INNER JOIN CONTRACT con     ON kho.CUSTOMEROID = con.CUSTOMEROID 
    INNER JOIN VW_CURRENT_CONTRACT_PERIOD ccp ON con.CONTRACT_ID = ccp.CONTRACT_ID 
    INNER JOIN CONTRACT_PERIOD cp    ON (ccp.CONTRACT_ID = cp.CONTRACT_ID AND ccp.CONTRACT_PERIOD = cp.CONTRACT_PERIOD) 
    INNER JOIN CONTRACT_EQUIP_PERIOD cep  ON cp.CONTRACT_PERIODOID = cep.CONTRACT_PERIODOID 
    INNER JOIN EQUIPMENT eq     ON cep.EQUIPMENTOID = eq.EQUIPMENTOID 
    INNER JOIN HOOK_OFFICE ho     ON khc.HOOK_OFFICEOID = ho.HOOK_OFFICEOID 
WHERE 
    eq.PRODUCT_ID = 'XXX' AND 
    (eq.LOCATION_DESCRIPTION IS NULL OR 
    ho.HOOK_OFFICE_LETTER || LPAD(khc.HOOK_NO, 5, '0') <> eq.LOCATION_DESCRIPTION) 

以下查詢將返回:

HOOKNO EQLOC 
G00754 (null) 
L02860 (null) 
L04052 L12345 
L01126 (null) 
L01348 (null) 
L01950 L56789 
L00857 (null) 
L04651 (null) 
L03762 (null) 

所以試過

UPDATE (SELECT ho.HOOK_OFFICE_LETTER || LPAD(khc.HOOK_NO, 5, '0') AS hookey, eq.LOCATION_DESCRIPTION AS eqloc 
     FROM KEY_HOOK_CURRENT khc 
      INNER JOIN KEY_HOLDING kho    ON khc.KEY_HOLDINGOID = kho.KEY_HOLDINGOID 
      INNER JOIN CONTRACT con     ON kho.CUSTOMEROID = con.CUSTOMEROID 
      INNER JOIN VW_CURRENT_CONTRACT_PERIOD ccp ON con.CONTRACT_ID = ccp.CONTRACT_ID 
      INNER JOIN CONTRACT_PERIOD cp    ON (ccp.CONTRACT_ID = cp.CONTRACT_ID AND ccp.CONTRACT_PERIOD = cp.CONTRACT_PERIOD) 
      INNER JOIN CONTRACT_EQUIP_PERIOD cep  ON cp.CONTRACT_PERIODOID = cep.CONTRACT_PERIODOID 
      INNER JOIN EQUIPMENT eq     ON cep.EQUIPMENTOID = eq.EQUIPMENTOID 
      INNER JOIN HOOK_OFFICE ho     ON khc.HOOK_OFFICEOID = ho.HOOK_OFFICEOID 
     WHERE 
     eq.PRODUCT_ID = 'XXX' AND 
     (eq.LOCATION_DESCRIPTION IS NULL OR (ho.HOOK_OFFICE_LETTER || LPAD(khc.HOOK_NO, 5, '0')) <> eq.LOCATION_DESCRIPTION)) 
SET hookno = eqloc 

    but getting 01733 - "virtual column not allowed" 

...和許多其他的查詢,包括合併,但沒有太多的經驗,這麼沒有太大運氣! :(

請注意:此查詢將運行每隔10min 24/7所以它應該是相當快的(如果可能的話),並更新只在必要時

您的幫助,將不勝感激

感謝。!

+1

在這裏,MERGE語句是要走的路,但您需要一些方法來識別設備表中的哪些行需要更新。設備表的主鍵是什麼? – Boneist

+0

設備ID – novacky

回答

1

考慮到設備表的主鍵是equipmentoid,我們可以按如下方式創建MERGE語句:

merge into equipment tgt 
using (select eq.equipmentoid, 
       ho.hook_office_letter || lpad(khc.hook_no, 5, '0') as hookno, 
       eq.location_description as eqloc 
     from key_hook_current khc 
      inner join key_holding kho    on khc.key_holdingoid = kho.key_holdingoid 
      inner join contract con     on kho.customeroid = con.customeroid 
      inner join vw_current_contract_period ccp on con.contract_id = ccp.contract_id 
      inner join contract_period cp    on (ccp.contract_id = cp.contract_id and ccp.contract_period = cp.contract_period) 
      inner join contract_equip_period cep  on cp.contract_periodoid = cep.contract_periodoid 
      inner join equipment eq     on cep.equipmentoid = eq.equipmentoid 
      inner join hook_office ho     on khc.hook_officeoid = ho.hook_officeoid 
     where 
      eq.product_id = 'XXX' and 
      (eq.location_description is null or 
      ho.hook_office_letter || lpad(khc.hook_no, 5, '0') <> eq.location_description)) src 
    on (tgt.equipmentoid = src.equipmentoid) 
when matched then 
update set tgt.location_description = src.hookno; 

所有我所做的就是採取您的選擇語句,添加到您的設備表的主鍵列的引用中,這允許我們將源子查詢連接回表並更新相關行。

+0

謝謝非常多骨科醫生!趕緊檢查出來......看起來很可疑;-) – novacky

+0

這就是合併聲明的美妙之處 - 如果你有sql語句生成你所追求的結果,通常只是將它作爲合併的源代碼部分插入。 (當然,有時您可以修改源查詢來移除目標表,並強制將聯接作爲merge語句的一部分,這可以使其運行更快,但我不確定這會在這種情況下起作用) – Boneist

+0

它工作! :)純粹AWESOMENESS。骨科醫生我從你的善意答案中學到的東西比從我今天看到的幾十個oracle手冊頁中學到的東西更多。非常感謝你! – novacky

0

看起來像你想將location_description分爲一個字母和5位數字代碼,並將其分配給HOOK_OFFICE_LETTER和HOOK_NO。

UPDATE ho 
    INNER JOIN KEY_HOLDING kho    ON khc.KEY_HOLDINGOID = kho.KEY_HOLDINGOID 
    INNER JOIN CONTRACT con     ON kho.CUSTOMEROID = con.CUSTOMEROID 
    INNER JOIN VW_CURRENT_CONTRACT_PERIOD ccp ON con.CONTRACT_ID = ccp.CONTRACT_ID 
    INNER JOIN CONTRACT_PERIOD cp    ON (ccp.CONTRACT_ID = cp.CONTRACT_ID AND ccp.CONTRACT_PERIOD = cp.CONTRACT_PERIOD) 
    INNER JOIN CONTRACT_EQUIP_PERIOD cep  ON cp.CONTRACT_PERIODOID = cep.CONTRACT_PERIODOID 
    INNER JOIN EQUIPMENT eq     ON cep.EQUIPMENTOID = eq.EQUIPMENTOID 
    INNER JOIN HOOK_OFFICE ho     ON khc.HOOK_OFFICEOID = ho.HOOK_OFFICEOID 

SET HOOK_OFFICE_LETTER = SUBSTRING(eq.location_description,1,1), 
--cut letter and assignto HOOK_OFFICE_LETTER 
khc.HOOK_NO = SUBSTRING(eq.location_description,2,5) 
--cut 5-digit code and assign to khc.HOOK_NO 
WHERE 
    eq.PRODUCT_ID = 'XXX' AND 
     (eq.LOCATION_DESCRIPTION IS NULL) OR 
     ((ho.HOOK_OFFICE_LETTER || LPAD(khc.HOOK_NO, 5, '0') <> eq.LOCATION_DESCRIPTION)) 

,不過也許你想更新eq.location_description到(ho.HOOK_OFFICE_LETTER || LPAD(khc.HOOK_NO,5, '0'),這樣 的值,可以使用下面的查詢:

UPDATE ho 
     INNER JOIN KEY_HOLDING kho    ON khc.KEY_HOLDINGOID = kho.KEY_HOLDINGOID 
     INNER JOIN CONTRACT con     ON kho.CUSTOMEROID = con.CUSTOMEROID 
     INNER JOIN VW_CURRENT_CONTRACT_PERIOD ccp ON con.CONTRACT_ID = ccp.CONTRACT_ID 
     INNER JOIN CONTRACT_PERIOD cp    ON (ccp.CONTRACT_ID = cp.CONTRACT_ID AND ccp.CONTRACT_PERIOD = cp.CONTRACT_PERIOD) 
     INNER JOIN CONTRACT_EQUIP_PERIOD cep  ON cp.CONTRACT_PERIODOID = cep.CONTRACT_PERIODOID 
     INNER JOIN EQUIPMENT eq     ON cep.EQUIPMENTOID = eq.EQUIPMENTOID 
     INNER JOIN HOOK_OFFICE ho     ON khc.HOOK_OFFICEOID = ho.HOOK_OFFICEOID 

    SET eq.location_description = (ho.HOOK_OFFICE_LETTER || LPAD(khc.HOOK_NO, 5, '0') 
    WHERE 
     eq.PRODUCT_ID = 'XXX' AND 
     (eq.LOCATION_DESCRIPTION IS NULL) OR 
     ((ho.HOOK_OFFICE_LETTER || LPAD(khc.HOOK_NO, 5, '0') <> eq.LOCATION_DESCRIPTION))