多连接' gotohell'更新

时间:2015-10-07 16:03:59

标签: sql oracle sql-update inner-join

我有这个返回简单表的选择查询 - 见下文。

我花了一整天的时间尝试写一个更新声明,当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"

......还有许多其他问题,包括合并但没有多少经验,所以运气不大! :(

请注意:此查询将每隔10分钟24/7运行,因此它应该非常快(如果可能)并且仅在必要时更新。

我们将不胜感激。

谢谢!

2 个答案:

答案 0 :(得分: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;

我所做的一切都是你的select语句,添加到你的设备表的主键列的引用中,这允许我们将源子查询加入表中并更新相关的行。

答案 1 :(得分: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))