Oracle临时分为两类,
一类是事务临时表,以on commit delete rows指示。按照指示含义,我们可以知道这类临时表数据是在commit之后就清除数据的。
一类是session临时表,以on commit preserve rows指示。同样,按照含义,表明这类表在commit之后还是保留数据的(直到session结束后会被自动清除)。
为什么要提Oracle的这两类临时表呢?他们的属性就这么点,还有啥好提的?呵呵。看下面例子:
--先创建一个事务临时表:
create global temporary table xxx(x int) on commit delete rows;
--执行如下语句:
SQL> declare
2 cursor cx is
3 select * from xxx;
4 type typ_cx is table of cx%rowtype index by pls_integer;
5 v_cx typ_cx;
6 begin
7 insert into xxx
8 select rownum from dual connect by rownum <= 20000;
9 open cx;
10 loop
11 fetch cx bulk collect into v_cx limit 3000;
12 exit when v_cx.count = 0;
13 dbms_output.put_line('Count: ' || v_cx.count);
14 commit;
15 end loop
16 commit;
17 end;
18 /
发生报错:
ORA-01410: invalid ROWID
ORA-06512: at line 12
觉得正常吗?
现在删除该临时表,创建一个session级的临时表,其他都不变:
--删除临时表
drop table xxx
--创建session临时表
create global temporary table xxx(x int) on commit preserve rows;
--执行之前那个过程
SQL> declare
2 cursor cx is
3 select * from xxx;
4 type typ_cx is table of cx%rowtype index by pls_integer;
5 v_cx typ_cx;
6 begin
7 insert into xxx
8 select rownum from dual connect by rownum <= 20000;
9 open cx;
10 loop
11 fetch cx bulk collect into v_cx limit 3000;
12 exit when v_cx.count = 0;
13 dbms_output.put_line('Count: ' || v_cx.count);
14 commit;
15 end loop
16 commit;
17 end;
18 /
PL/SQL procedure successfully completed
执行成功!!这是为什么?
看代码知道,这个过程就是将20000个数字的数据插入到临时表,然后打开临时表的游标,将这些数字以每批3000分批从游标中取出并打印对应批次的数量。打印后,执行一个commit命令。问题就出在这个commit命令上,因为commit表示一个提交,而事务临时表在commit之后,数据随之被清空,导致下次fetch游标中的数据时无法取到,从而发生第一个过程执行时的错误。而session临时表就不会有这个问题。
另外,需要注意的是,session临时表是在整个session期间有效的,因此在同个session期间如果执行了多次,会重复的插入数据到该表中。开发的时候要注意这个现象,否则很容易出现累加效应。
一类是事务临时表,以on commit delete rows指示。按照指示含义,我们可以知道这类临时表数据是在commit之后就清除数据的。
一类是session临时表,以on commit preserve rows指示。同样,按照含义,表明这类表在commit之后还是保留数据的(直到session结束后会被自动清除)。
为什么要提Oracle的这两类临时表呢?他们的属性就这么点,还有啥好提的?呵呵。看下面例子:
--先创建一个事务临时表:
create global temporary table xxx(x int) on commit delete rows;
--执行如下语句:
SQL> declare
2 cursor cx is
3 select * from xxx;
4 type typ_cx is table of cx%rowtype index by pls_integer;
5 v_cx typ_cx;
6 begin
7 insert into xxx
8 select rownum from dual connect by rownum <= 20000;
9 open cx;
10 loop
11 fetch cx bulk collect into v_cx limit 3000;
12 exit when v_cx.count = 0;
13 dbms_output.put_line('Count: ' || v_cx.count);
14 commit;
15 end loop
16 commit;
17 end;
18 /
发生报错:
ORA-01410: invalid ROWID
ORA-06512: at line 12
觉得正常吗?
现在删除该临时表,创建一个session级的临时表,其他都不变:
--删除临时表
drop table xxx
--创建session临时表
create global temporary table xxx(x int) on commit preserve rows;
--执行之前那个过程
SQL> declare
2 cursor cx is
3 select * from xxx;
4 type typ_cx is table of cx%rowtype index by pls_integer;
5 v_cx typ_cx;
6 begin
7 insert into xxx
8 select rownum from dual connect by rownum <= 20000;
9 open cx;
10 loop
11 fetch cx bulk collect into v_cx limit 3000;
12 exit when v_cx.count = 0;
13 dbms_output.put_line('Count: ' || v_cx.count);
14 commit;
15 end loop
16 commit;
17 end;
18 /
PL/SQL procedure successfully completed
执行成功!!这是为什么?
看代码知道,这个过程就是将20000个数字的数据插入到临时表,然后打开临时表的游标,将这些数字以每批3000分批从游标中取出并打印对应批次的数量。打印后,执行一个commit命令。问题就出在这个commit命令上,因为commit表示一个提交,而事务临时表在commit之后,数据随之被清空,导致下次fetch游标中的数据时无法取到,从而发生第一个过程执行时的错误。而session临时表就不会有这个问题。
另外,需要注意的是,session临时表是在整个session期间有效的,因此在同个session期间如果执行了多次,会重复的插入数据到该表中。开发的时候要注意这个现象,否则很容易出现累加效应。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12932950/viewspace-682606/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/12932950/viewspace-682606/