PL / SQL - 循环插入和选择

时间:2014-06-16 04:23:08

标签: sql oracle loops plsql insert

我想要一个可重用的脚本,可以通过交换变量值进行配置。我希望能够循环遍历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;

此示例的问题:

  • 此示例返回选择查询周围的错误。
  • 当我删除select语句时,示例代码返回错误,其中包含'numList'中的索引。

有关正确处理此方案的方法的任何建议吗?

1 个答案:

答案 0 :(得分:2)

好的,首先,上面的代码包含一些问题。如果不将它们存储在带有INTO关键字的变量中,则不能在PL / SQL中使用选择。

为了重现您的问题,我使用这些脚本来创建表和序列:

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