這裡說的“序列”不是 Oracle 中的 sequence ,而是產生一個從 n 到 m 的序列表,如下所示:
01
SEQ
02
----------
03
1
04
2
05
3
06
4
07
5
08
6
09
7
10
8
11
9
12
10
序列表有什麼用處呢,用處可大了,以後的文章中將大量用到。
我們先從產生 1 到 m 的序列表開始吧。
第一種做法是先建一個表,然後循環插入:
01
create
table
t_seq
02
(
03
seq
int
04
);
05
06
declare
07
i number;
08
begin
09
for
i
in
1..10 loop
10
insert
into
t_seq
values
( i );
11
end
loop;
12
commit
;
13
end
;
這種做法的可移植性非常好,幾乎任何數據庫都可以使用,即使某些 DBMS 不支持 for 循環(例如SQL Server),完全可以借助其他循環語句例如 while 實施。
第二種,借助 rownum 偽列:
1
select
rownum seq
from
user_objects
where
rownum<10;
通常我們借助一個記錄比較多的系統表來獲得 rownum 。
對於沒有類似 rownum 這項功能的SQL Server,可以借助 identity 的遞增來實現:
1
select
seq=identity(
int
,1,1)
into
#t
from
sys.objects ;
2
select
seq
from
#t
where
seq<=10;
或者
1
select
top
10 seq=identity(
int
,1,1)
into
#t
from
sys.objects ;
2
select
seq
from
#t;
或者借助分析函數 row_number() 實現:
1
select
top
10 row_number() over (
order
by
object_id)
from
sys.objects;
當然實現的方式有很多,但是這種方法產生的序列受限於所借助的表,產生一個很大的序列就比較頭痛了,而且產生I/O損耗是不可避免的。可以總結為直觀,可移植性不佳。
第三種方法,遞歸查詢,暫時發現能在 Oracle 10g 以上使用:
1
select
level
seq
from
dual
connect
by
level
<=10
這條語句一個 I/O 都不產生:
01
------------------------------------------------------------------------------
02
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
03
------------------------------------------------------------------------------
04
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
05
| 1 | SORT AGGREGATE | | 1 | | |
06
| 2 | CONNECT BY WITHOUT FILTERING| | | | |
07
| 3 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
08
------------------------------------------------------------------------------
09
10
11
Statistics
12
----------------------------------------------------------
13
0 recursive calls
14
0 db block gets
15
0 consistent gets
16
0 physical reads
17
0 redo size
18
508 bytes sent via SQL*Net to clIEnt
19
469 bytes received via SQL*Net from clIEnt
20
2 SQL*Net roundtrips to/from clIEnt
21
1 sorts (memory)
22
0 sorts (disk)
23
1 rows processed