多连接 'gotohell' 更新

Multi-join 'gotohell' update

我有这个 select 查询 returns 简单 table - 见下文。

我花了一整天的时间试图写一个更新语句,当 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)

查询 returns 如下:

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,因此它应该非常快(如果可能)并且仅在必要时更新。

我们将不胜感激。

谢谢!

鉴于设备table的主键是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 语句,添加到对你设备 table 的主键列的引用中,这允许我们将源子查询连接回 table 并更新相关行。

看起来你想将 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))