提问人:Confused 提问时间:10/22/2023 最后编辑:Thorsten KettnerConfused 更新时间:10/22/2023 访问量:38
如何使用带条件的批量收集 for 循环
How to use bulk collect for loop with conditions
问:
我有一个要求,其中源表中的每一行的标题都是重复的。我必须创建plsql过程,将它们插入到具有通用标识符的单独的标题和行表中。我目前正在使用带有 if else 条件的简单 for 循环构造来维护标题和行表中的唯一标识 (invoiceid)
例如:源表
因夫纳姆 | 线型 | 量 | 行号 |
---|---|---|---|
123 | 项目 | 100 | 1 |
123 | 税 | 20 | 2 |
446 | 项目 | 100 | 1 |
446 | 项目 | 100 | 2 |
446 | 税 | 20 | 3 |
标题表
InvId | InvNum (英语) | Amt(阿姆特酒店) |
---|---|---|
100 | 123 | 120 |
101 | 446 | 220 |
线表
InvId | 线型 | 量 | 行号 |
---|---|---|---|
100 | 项目 | 100 | 1 |
100 | 税 | 20 | 2 |
101 | 项目 | 100 | 1 |
101 | 项目 | 100 | 2 |
101 | 税 | 20 | 3 |
我尝试了带有 if else 条件的简单 forloop 构造。但是有没有更好的方法可以做到这一点
答:
0赞
Littlefoot
10/22/2023
#1
按照我的理解,你需要一个连接,而不是一个循环。
示例数据:
SQL> with
2 source (invnum, linetype, amount, linenumber) as
3 (select 123, 'ITEM', 100, 1 from dual union all
4 select 123, 'TAX' , 20, 2 from dual union all
5 select 446, 'ITEM', 100, 1 from dual union all
6 select 446, 'ITEM', 100, 2 from dual union all
7 select 446, 'TAX' , 20, 3 from dual
8 ),
9 header (invid, invnum, amt) as
10 (select 100, 123, 120 from dual union all
11 select 101, 446, 220 from dual
12 )
生成该结果的查询:
13 select h.invid, s.linetype, h.amt, s.linenumber
14 from header h join source s on s.invnum = h.invnum
15 order by h.invid, s.linenumber;
INVID LINE AMT LINENUMBER
---------- ---- ---------- ----------
100 ITEM 120 1
100 TAX 120 2
101 ITEM 220 1
101 ITEM 220 2
101 TAX 220 3
SQL>
如果它必须是 PL/SQL 过程,只需将该段代码移入其中;例如:
create or replace procedure p_line is
begin
insert into line_table (invid, line, amt, linenumber)
select h.invid, s.linetype, h.amt, s.linenumber
from header h join source s on s.invnum = h.invnum;
end;
/
现在,您可以修改它并添加参数(“仅插入所需的行”)等。invid
0赞
Thorsten Kettner
10/22/2023
#2
可以使用两个插入件。由于两者都查询相同的数据集,因此它们会获得相同的 invnum,您可以从中安全地创建 invid(甚至当您聚合每个 invnum 时)。DENSE_RANK
ROW_NUMBER
insert into header_table (invid, invnum, amt)
select
row_number() over (order by invnum) + 99,
invnum,
sum(amount)
from source_table
group by invnum;
和
insert into line_table (invid, linetype, amount, linenumber)
select
dense_rank() over (order by invnum) + 99,
linetype,
amount,
linenumber
from source_table;
但是,冗余存储数据并不是一个好主意。标题表中不应有总金额,因为可以从行表条目中选择此金额。
评论
invoiceid