我有两个表tab1和tab2,每个表都有两列acc_num和prod_code。我需要从tab1更新tab2中的prod_code。以下是两个表中的示例数据:
TAB1
acnum Prod
-------------------
1 A
2 B
2 C
3 X
3 X
Tab2
acnum Prod
-------------------
1 null
2 null
2 null
3 null
3 null
对于更新后的第二个表,所有不同的代码应该连接在一起。以下是示例输出。
Tab2
acnum Prod
-------------------
1 A
2 B|C
2 B|C
3 X
3 X
我能够通过PL / SQL实现这一目标,但需要很长时间才能完成。 (实际表格有数百万条记录)。以下是我正在使用的代码。
DECLARE
l_acnum dbms_sql.varchar2a;
l_prod dbms_sql.varchar2a;
l_prod2 VARCHAR2(10):= NULL;
l_count NUMBER := 0;
CURSOR cr_acnum
IS
SELECT DISTINCT(acnum) FROM tab1;
CURSOR cr_prod(l_acnum_dum IN VARCHAR2)
IS
SELECT prod FROM tab1 WHERE acnum = l_acnum_dum;
BEGIN
OPEN cr_acnum;
FETCH cr_acnum bulk collect INTO l_acnum;
CLOSE cr_acnum;
FOR i IN l_acnum.first .. l_acnum.last
LOOP
OPEN cr_prod(l_acnum(i));
FETCH cr_prod bulk collect INTO l_prod;
CLOSE cr_prod;
FOR m IN l_prod.first .. l_prod.last
LOOP
IF m <> 1 THEN
IF l_prod(m) = l_prod(m-1) THEN
l_prod2 := l_prod(m);
ELSE
l_prod2 := l_prod2||'|'||l_prod(m);
END IF;
ELSE
l_prod2 := l_prod(m);
END IF;
END LOOP;
UPDATE tab2 SET prod = l_prod2 WHERE acnum = l_acnum(i);
END LOOP;
END;
此pl / sql块需要很长时间才能完成。无论如何,我可以通过查询而不是PL / SQL实现相同的功能,或者可以通过高效的PL / SQL实现相同的功能。我也尝试了BULK COLLECT,但没有用。数据在Oracle DB中。非常感谢你的时间。
答案 0 :(得分:1)
这将连接这些值,只要它们不超过某个总长度即可。如果存在任何欺骗行为,您可能还需要执行子查询来重复数据删除。
更新:这是LISTAGG
update table2 set Prod = (
SELECT LISTAGG(t1.Prod, ', ') WITHIN GROUP (ORDER BY t1.Prod) "Prod"
FROM Table1 t1
where t1.acnum = table2.acnum)
答案 1 :(得分:0)
感谢大家的意见。我使用你的输入得到了同样的结果。我使用了两步解决方案:
步骤1)为产品和帐户号创建查找表。
create table lkup_tbl
as SELECT acnum, LISTAGG(Prod, '|') WITHIN GROUP (ORDER BY Prod) product
FROM (select distinct acnum, Prod from tab1) tab
GROUP BY acnum;
步骤2)现在通过加入此查找表来更新所有表。
update tab2 t1
set (t1.Prod) = (select product from lkup_tbl t2
where t2.acnum = t1.acnum
);