2015-10-07 34 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))