PLSQL 中的 LIMIT 子句用法
Posted
技术标签:
【中文标题】PLSQL 中的 LIMIT 子句用法【英文标题】:LIMIT clause usage in PLSQL 【发布时间】:2021-09-24 14:24:50 【问题描述】:我有一个用于提取数据然后插入它们的过程。我的问题是我正在使用 BULK COLLECTION。我的目标是每次都提取例如 10,000 条数据,然后插入这 10,000 条记录。但是在我的脚本中,我可以用那个值来限制它,但它不会插入更多。例如,我有 6 条记录,我用 4 条带 LIMIT 子句。我想要的是程序应该首先插入 4 条记录,然后提取剩余的 2 条记录。
我可以简要描述一下问题。我对脚本中的任何修复建议持开放态度。从现在开始谢谢你。
我解决了我的问题在下面添加了新版本的脚本,谢谢大家
create or replace procedure GPU_DATA_EXTRACTOR_TEST(pid_billdate DATE) is
v_cnt NUMBER;
c_limit CONSTANT PLS_INTEGER DEFAULT 4;
CURSOR c1 IS
SELECT DISTINCT intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab
WHERE abr.CHRG_TP = 'INSTALLMENT'
AND abr.TAX_CATG_ID = 'NOTAX'
AND abr.acct_bill_id = ab.acct_bill_id
AND ab.bill_date = pid_billdate;
TYPE prod_ids_t IS TABLE OF apld_bill_rt.intl_prod_id%TYPE INDEX BY PLS_INTEGER;
l_prod_ids prod_ids_t;
begin
execute immediate 'truncate table GPU_INV_TEST';
v_cnt := 0;
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO l_prod_ids LIMIT c_limit;
EXIT WHEN l_prod_ids.COUNT = 0;
FOR indx IN 1 .. l_prod_ids.COUNT
loop
INSERT INTO GPU_INV_TEST
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba2.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
prod p,
FCBSADM.PROD_DST pds,
bill_acct_prod bap,
bill_acct ba1,
bill_acct ba2,
prod_cmpg pg
WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba2.intl_bill_acct_id = bap.intl_bill_acct_id
AND bap.intl_prod_id = abr.intl_prod_id
AND ABR.CHRG_TP = 'INSTALLMENT'
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
AND p.intl_prod_id = pg.intl_prod_id(+)
AND ABR.intl_prod_id = l_prod_ids(indx)
UNION
SELECT AB.ACCT_BILL_ID,
AB.BILL_NO,
AB.INV_ID,
AB.BILL_DATE,
ba1.bill_acct_id,
ba1.bill_acct_id parent_bill_acct_id,
AB.DUE_DATE,
PG.CMPG_ID,
ABR.NET_AMT,
AB.DUE_AMT,
P.PROD_NUM,
pds.DST_ID,
ABR.DESCR,
p.intl_prod_id
FROM apld_bill_rt abr,
acct_bill ab,
prod p,
FCBSADM.PROD_DST pds,
bill_acct_prod bap,
bill_acct ba1,
prod_cmpg pg
WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
--AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
AND ba1.intl_bill_acct_id = bap.intl_bill_acct_id
AND bap.intl_prod_id = abr.intl_prod_id
AND ABR.CHRG_TP = 'INSTALLMENT'
AND bap.intl_prod_id = pds.intl_prod_id
AND bap.intl_prod_id = p.intl_prod_id
AND p.intl_prod_id = pg.intl_prod_id(+)
AND ABR.intl_prod_id = l_prod_ids(indx);
v_cnt := v_cnt + 1;
IF MOD (v_cnt, 4) = 0
THEN
COMMIT;
END IF;
end loop;
COMMIT;
END LOOP;
CLOSE c1;
end;
【问题讨论】:
出于兴趣,为什么abr.TAX_CATG_ID
而abr.acct_bill_id
?大写的意义是什么?
@WilliamRobertson 没有显着差异
【参考方案1】:
您需要一个循环来获取多个记录子集。示例 sn-p:
...
loop
FETCH c1 BULK COLLECT INTO l_prod_ids LIMIT c_limit;
exit when l_prod_ids.count = 0;
FOR indx IN 1 .. l_prod_ids.COUNT
...
end loop;
CLOSE c1;
...
顺便说一句,执行数千个单独的 INSERT 语句会导致性能下降。您应该使用 FORALL 语法(这不是循环)从您的集合中执行基于集合的插入操作。 Find out more.
当您可以只使用纯 SQL INSERT INTO ... SELECT ... FROM
语句时,您还应该考虑是否应该使用集合。这将比 FORALL 操作执行得更好。
【讨论】:
"which is not a loop" 它不会多次执行插入,但它确实是一个循环,因为在执行插入之前必须填充绑定变量数组。 @JeffHolt 毫无疑问,PL/SQL 引擎在内部必须遍历数组绑定变量,但从语法上讲,对于程序员来说,它是处理数组的单个语句。 您好,您的建议有效。我为问题添加了新的解决方案。谢谢以上是关于PLSQL 中的 LIMIT 子句用法的主要内容,如果未能解决你的问题,请参考以下文章