处理重复的MERGE

时间:2019-04-01 07:02:35

标签: sql oracle oracle10g

我有表的订单和打算

oano  code  slno  
0001  swg1   1
0001  swg2   2
0001  swg1   3
0001  swg4   4
0001  swg1   5

打算

intend   oano  code  slno
i/1      0001   swg1  1
i/1      0001   swg1  3
i/1      0001   swg2  2  
i/3      0001   swg4  4
i/3      0001   swg1  5

我想如上所述基于OA表更新打算表中的序列号。 我使用的合并语句是

MERGE INTO ITBG_Intend_ITEMS target
USING (select oano, pcode, slno
           from itbg_order_items
           group by oano, pcode,SLNO
      ) source
ON
(target.icode = source.pcode and target.Oano = source.Oano )
WHEN MATCHED THEN UPDATE
    SET target.slno= source.slno

;

显示错误:ORA-30926:无法在源表中获得稳定的行集

请帮助

2 个答案:

答案 0 :(得分:0)

如果源表中目标表中的记录有多个匹配项,则

Merge将不起作用。相反,您可以使用update + join

UPDATE 
(
SELECT ITBG_Intend_ITEMS.slno as target_slno, itbg_order_items.slno as source_slno
 FROM ITBG_Intend_ITEMS
 INNER JOIN itbg_order_items
 ON ITBG_Intend_ITEMS.icode = itbg_order_items.pcode and ITBG_Intend_ITEMS.Oano = itbg_order_items.Oano
) joined
SET joined.target_slno = joined.source_slno

答案 1 :(得分:0)

问题在于,对于oano = 0001code = swg1,您拥有slno的三个值:1、3、5。因此Oracle不知道要使用哪个值。如果要最小值或最大值,请在源部分中使用min()max(),然后从slno子句中删除group by

  merge into itbg_intend_items tgt
  using (select oano, pcode, min(slno) slno
           from itbg_order_items
           group by oano, pcode) src
  on (tgt.icode = src.pcode and tgt.oano = src.oano)
  when matched then update set tgt.slno= src.slno

但是,如果您想分配出现在源表中的所有值,则必须以某种方式关联行。例如,可以通过将数字分配给行并以这种方式联接表来完成这种“某种方式”的操作。此类准备好的数据可用作您的merge语句中的源:

merge into itbg_intend_items tgt
using (
  select rwd, oano, pcode, slno
    from (select oano, pcode, slno, 
                 row_number() over (partition by oano, pcode order by null) rn 
           from itbg_order_items)
    join (select rowid rwd, oano, icode pcode, 
                 row_number() over (partition by oano, icode order by null) rn 
           from itbg_intend_items)
    using (oano, pcode, rn)) src
on (tgt.icode = src.pcode and tgt.oano = src.oano and tgt.rowid = src.rwd)
when matched then update set tgt.slno= src.slno

dbfiddle demo

当然,可能存在一些问题,例如源中的值不足以填充目标。或者,您可能需要特定的顺序(在这种情况下,请更改row_number()的顺序)。一切都可以完成,但是您必须告诉我们在这种情况下您想要什么。