![](/img/trans.png)
[英]How to optimize insert from select in For loop in Oracle PL/SQL
[英]PL/SQL - Loop insert and select
我想要一個可重用的腳本,可以通過換出變量值進行配置。 我希望能夠遍歷tag_ids
的集合並為每個標簽插入一行。 我也想在提交之前檢查插入的任何一側以進行視覺驗證。
到目前為止,這是我嘗試過的:
set verify off;
set serveroutput on;
define uname = 'foobar'
define f_name = 'foo'
define l_name = 'bar'
declare
type numListType is table of number;
numList numListType;
begin
numList := numListType(432,433,434,435);
for i in numList.FIRST..numList.LAST loop
dbms_output.put_line('EXPECTING 0');
select count(*)
from security_tag_tbl
where tag_id = numList(i);
dbms_output.put_line('INSERTING ROW');
insert into security_tag_tbl (id, username, first_name, last_name, tag_id)
values (security_tag_tbl_seq.nextval, '&uname', '&f_name', '&l_name', numList(i));
dbms_output.put_line('EXPECTING 1');
select count(*)
from security_tag_tbl
where tag_id = numList(i);
end loop;
end;
/
set serveroutput off;
set verify on;
此樣本存在以下問題:
關於解決這種情況的正確方法有何建議?
好的,首先,上面的代碼包含一些問題。 如果不將選擇存儲在帶有INTO關鍵字的變量中,則無法使用它們。
為了重現您的問題,我使用以下腳本創建了表和序列:
create table security_tag_tbl (id number, username varchar2(200), first_name varchar2(200), last_name varchar2(200), tag_id number);
create sequence security_tag_tbl_seq;
然后,我將您的代碼修改為:
set verify off;
set serveroutput on;
define uname = 'foobar'
define f_name = 'foo'
define l_name = 'bar'
declare
type numListType is table of number;
numList numListType;
firstcount number;
secondcount number;
begin
numList := numListType(432,433,434,435);
for i in numList.FIRST..numList.LAST loop
dbms_output.put_line('EXPECTING 0');
select count(*)
into firstcount
from security_tag_tbl
where tag_id = numList(i);
dbms_output.put_line('GOT ' || firstcount);
dbms_output.put_line('INSERTING ROW');
insert into security_tag_tbl (id, username, first_name, last_name, tag_id)
values (security_tag_tbl_seq.nextval, '&uname', '&f_name', '&l_name', numList(i));
dbms_output.put_line('EXPECTING 1');
select count(*)
into secondcount
from security_tag_tbl
where tag_id = numList(i);
dbms_output.put_line('GOT ' || secondcount);
end loop;
end;
/
set serveroutput off;
set verify on;
現在,您將獲得有關正在發生的情況的視覺反饋。 下一個問題是,當您沒有獲得期望的結果時該怎么辦? 您可以進行如下構造:根據這些計數的結果來提交或回滾事務:
set verify off;
set serveroutput on;
define uname = 'foobar'
define f_name = 'foo'
define l_name = 'bar'
declare
type numListType is table of number;
numList numListType;
firstcount number;
secondcount number;
errorocured boolean := false;
begin
numList := numListType(432,433,434,435);
for i in numList.FIRST..numList.LAST loop
dbms_output.put_line('EXPECTING 0');
select count(*)
into firstcount
from security_tag_tbl
where tag_id = numList(i);
dbms_output.put_line('GOT ' || firstcount);
if (firstcount != 0) then
errorocured := true;
end if;
dbms_output.put_line('INSERTING ROW');
insert into security_tag_tbl (id, username, first_name, last_name, tag_id)
values (security_tag_tbl_seq.nextval, '&uname', '&f_name', '&l_name', numList(i));
dbms_output.put_line('EXPECTING 1');
select count(*)
into secondcount
from security_tag_tbl
where tag_id = numList(i);
dbms_output.put_line('GOT ' || secondcount);
if (secondcount != 1) then
errorocured := true;
end if;
end loop;
if errorocured = true then
dbms_output.put_line('Something wend wrong, rolling back batch');
rollback;
else
dbms_output.put_line('Everything ok, committing batch');
commit;
end if;
end;
/
set serveroutput off;
set verify on;
如果您打算將此代碼用於更大的數字或記錄,則可能還需要研究批量操作。 可以在這里找到關於它的好的文檔: http : //www.oracle-base.com/articles/9i/bulk-binds-and-record-processing-9i.php
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.