PLSQL 中的 LIMIT 子句用法
LIMIT clause usage in PLSQL
我有一个用于提取数据然后插入数据的程序。我的问题是我正在使用 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;
您需要一个循环来获取多个记录子集。示例片段:
...
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 操作执行得更好。
我有一个用于提取数据然后插入数据的程序。我的问题是我正在使用 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;
您需要一个循环来获取多个记录子集。示例片段:
...
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 操作执行得更好。