1、oracle的僞列
oracle系統為了實作完整的關系資料庫功能,系統專門提供了一組稱為僞列(Pseudocolumn)的資料庫列,這些列不是在建立對象時由我們完成的,而是在我們建立時由Oracle完成的。Oracle目前常見的僞列:
currval 和 nextval 使用序列号的保留字
CURRVAL:傳回目前sequence值
NEXTVAL:增加sequence并傳回下一個值
一般用法:
sequence.CURRVAL
sequence.NEXTVAL
level 查詢資料所對應的級
分級查詢是oracle提供的遞歸查詢文法,在這裡不做展開。隻有在分級查詢下,才可以使用以下僞列:
CONNECT_BY_ISCYCLE Pseudocolumn
CONNECT_BY_ISLEAF Pseudocolumn
LEVEL Pseudocolumn
Version Query Pseudocolumns
Version Query僞列隻有在Flashback Version Query時才有效,内容如下:
VERSIONS_STARTSCN and VERSIONS_STARTTIME
VERSIONS_ENDSCN and VERSIONS_ENDTIME
VERSIONS_XID
VERSIONS_OPERATION
l COLUMN_VALUE Pseudocolumn
l OBJECT_ID Pseudocolumn
l OBJECT_VALUE Pseudocolumn
l ORA_ROWSCN Pseudocolumn
l XMLDATA Pseudocolumn
rowid 記錄的唯一辨別
rownum 限制查詢結果集的數量
在對普通表做查詢時,比較常用的僞列有:ORA_ROWSCN、ROWID、ROWNUM。
ORA_ROWSCN
雖然叫ORA_ROWSCN,不過預設情況下,查詢出的該值是從資料檔案塊頭擷取的,也就是說,查詢出的是block的最近事務的scn,而不是精确到row的scn。
在建立表時,可以指定ROWDEPENDENCIES來使ora_rowscn真正記錄行一級的scn。
看一下ROWDEPENDENCIES 的定義:Specify ROWDEPENDENCIES if you want to enable row-level dependency tracking(追蹤). This setting
is useful primarily to allow for parallel propagation in replication environments. It increases the size of each row by 6 bytes.
從這裡也可以看出一個SCN占用的空間(6 bytes)。SCN的最大值是0xffff.ffffffff,共48位。包括2bytes的高位位元組(SCN
wrap)和4bytes的低位位元組(SCN base)。
SQL>select ora_rowscn,username from t;
ORA_ROWSCN USERNAME
---------- ------------------------------
86516279 SYSTEM
86516279 SYS
86516279 OUTLN
86516279 LINCINQ
86516279 TEST
86516279 LINC
86516279 SPLEXUC
86516279 DIP
86516279 TSMSYS
86516279 WMSYS
86516279 DBSNMP
11 rows selected.
需要查詢scn對于的具體時間,可以用函數SCN_TO_TIMESTAMP
SQL>alter session set nls_timestamp_format='yyyy-mm-dd hh24:mi:ss';
Session altered.
SQL>select scn_to_timestamp(ora_rowscn),username from t;
SCN_TO_TIMESTAMP(ORA_ROWSCN) USERNAME
------------------------------ ------------------------------
2011-06-01 13:13:31 SYSTEM
2011-06-01 13:13:31 SYS
2011-06-01 13:13:31 OUTLN
2011-06-01 13:13:31 LINCINQ
2011-06-01 13:13:31 TEST
2011-06-01 13:13:31 LINC
2011-06-01 13:13:31 SPLEXUC
2011-06-01 13:13:31 DIP
2011-06-01 13:13:31 TSMSYS
2011-06-01 13:13:31 WMSYS
2011-06-01 13:13:31 DBSNMP
ROWID
rowid是一種特殊類型的列,又叫做rowid僞列。rowid僞列可以向正常列一樣使用sql select語句通路。oracle資料庫每一行都有一個
rowid僞列。rowid表示特定行的特定位址。rowid 僞列可以用rowid資料類型來定義。
rowid與磁盤驅動器中的特定位置相關。是以,rowid是擷取某個行最快速的方法。然面,一個行的rowid會随着資料庫的解除安裝和重新加載而發生變化。基于這一點考慮,我們不推薦在多個事務代碼中使用rowid僞列的值。
使用者無法使用sql語句來設定标準的rowid僞列的數值。
使用者可以定義rowid類型的列或者變量,但是oracle并不保證存在這些列或者變量中的數值就是有效的rowid
rowid就是表記錄存在于檔案系統中的實體位置,索引結構中包含rowid,是以通過索引能快速的定位表中的記錄.
rowid的存在時是了能根據它找到表的這條記錄存在哪個具體的實體位置,我們需要知道它在哪個資料檔案,在哪個block,在哪一行
這就是修改某列時需要提供rowid的原因。
Rowid的概念:rowid是一個僞列,既然是僞列,那麼這個列就不是使用者定義,而是系統自己給加上的。對每個表都有一個rowid的僞列,但是表中并不實體存儲ROWID列的值。不過你可以像使用其它列那樣使用它,但是不能删除改列,也不能對該列的值進行修改、插入。一旦一行資料插入資料庫,則rowid在該行的生命周期内是唯一的,即即使該行産生行遷移,行的rowid也不會改變。
Rowid是基于64位編碼的18個字元,格式如下:
data_object_id file_id block_number row_number
---------- ---------- ---------- ----
OOOOOO FFF BBBBBB RRR
SQL>select rowid,username from t;
ROWID USERNAME
------------------ ------------------------------
AAAE0LAAOAABQqMAAA SYSTEM
AAAE0LAAOAABQqMAAB SYS
AAAE0LAAOAABQqMAAC OUTLN
AAAE0LAAOAABQqMAAD LINCINQ
AAAE0LAAOAABQqMAAE TEST
AAAE0LAAOAABQqMAAF LINC
AAAE0LAAOAABQqMAAG SPLEXUC
AAAE0LAAOAABQqMAAH DIP
AAAE0LAAOAABQqMAAI TSMSYS
AAAE0LAAOAABQqMAAJ WMSYS
AAAE0LAAOAABQqMAAK DBSNMP
通過dbms_rowid包,我們可以獲得rowid對應的記錄詳細資訊。
SQL>select dbms_rowid.rowid_object('&1') data_object_id#,
dbms_rowid.rowid_relative_fno('&1') rfile#,
dbms_rowid.rowid_block_number('&1') block#,
dbms_rowid.rowid_row_number('&1') row# from dual;
Enter value for 1: AAAE0LAAOAABQqMAAA
old 1: select dbms_rowid.rowid_object('&1') data_object_id#,
new 1: select dbms_rowid.rowid_object('AAAE0LAAOAABQqMAAA') data_object_id#,
old 2: dbms_rowid.rowid_relative_fno('&1') rfile#,
new 2: dbms_rowid.rowid_relative_fno('AAAE0LAAOAABQqMAAA') rfile#,
old 3: dbms_rowid.rowid_block_number('&1') block#,
new 3: dbms_rowid.rowid_block_number('AAAE0LAAOAABQqMAAA') block#,
old 4: dbms_rowid.rowid_row_number('&1') row# from dual
new 4: dbms_rowid.rowid_row_number('AAAE0LAAOAABQqMAAA') row# from dual
DATA_OBJECT_ID# RFILE# BLOCK# ROW#
--------------- ---------- ---------- ----------
19723 14 330380 0
ROWNUM
在對表的查詢中,每傳回一條記錄,rownum僞列就傳回一個數字,代表查詢傳回的行的編号。
SQL>select rownum,username from t;
ROWNUM USERNAME
1 SYSTEM
2 SYS
3 OUTLN
4 LINCINQ
5 TEST
6 LINC
7 SPLEXUC
8 DIP
9 TSMSYS
10 WMSYS
11 DBSNMP
從下面的例子可以看出,rownum傳回的是查詢過程中傳回記錄的順序,并不是查詢結果的序列号。
SQL>select rownum,username from t order by username;
SQL>select rownum,username from (select username from t order by username);
1 DBSNMP
2 DIP
3 LINC
5 OUTLN
6 SPLEXUC
7 SYS
8 SYSTEM
9 TEST
10 TSMSYS
11 WMSYS
對于 Oracle 的 rownum 問題,很多資料都說不支援>,>=,=,between...and,隻能用以上符号(<、<=、!=),并非說用>,>=,=,between..and 時會提示SQL文法錯誤,而是經常是查不出一條記錄來,還會出現似乎是莫名其妙的結果來,其實您隻要了解好了這個 rownum 僞列的意義就不應該感到驚奇,同樣是僞列,rownum 與 rowid 可有些不一樣,下面以例子說明
:
假設某個表 t1(c1) 有 20 條記錄
如果用 select rownum,c1 from t1 where rownum < 10, 隻要是用小于号,查出來的結果很容易地與一般了解在概念上能達成一緻,應該不會有任何疑問的。
可如果用 select rownum,c1 from t1 where rownum > 10 (如果寫下這樣的查詢語句,這時候在您的頭腦中應該是想得到表中後面10條記錄),你就會發現,顯示出來的結果要讓您失望了,也許您還會懷疑是不誰删了一些記錄,然後檢視記錄數,仍然是 20 條啊?那問題是出在哪呢?
先好好了解 rownum 的意義吧。因為ROWNUM是對結果集加的一個僞列,即先查到結果集之後再加上去的一個列 (強調:先要有結果集)。簡單的說 rownum 是對符合條件結果的序列号。它總是從1開始排起的。是以你選出的結果不可能沒有1,而有其他大于1的值。是以您沒辦法期望得到下面的結果集:
11 aaaaaaaa
12 bbbbbbb
13 ccccccc
.................
rownum >10 沒有記錄,因為第一條不滿足去掉的話,第二條的ROWNUM又成了1,是以永遠沒有滿足條件的記錄。或者可以這樣了解:
ROWNUM是一個序列,是oracle資料庫從資料檔案或緩沖區中讀取資料的順序。它取得第一條記錄則rownum值為1,第二條為2,依次類推。如果你用>,>=,=,between...and這些條件,因為從緩沖區或資料檔案中得到的第一條記錄的rownum為1,則被删除,接着取下條,可是它的rownum還是1,又被删除,依次類推,便沒有了資料。
有了以上從不同方面建立起來的對 rownum 的概念,那我們可以來認識使用 rownum 的幾種現像
1. select rownum,c1 from t1 where rownum != 10 為何是傳回前9條資料呢?它與 select rownum,c1 from tablename where rownum < 10 傳回的結果集是一樣的呢?
因為是在查詢到結果集後,顯示完第 9 條記錄後,之後的記錄也都是 != 10,或者 >=10,是以隻顯示前面9條記錄。也可以這樣了解,rownum 為9後的記錄的 rownum為10,因條件為 !=10,是以去掉,其後記錄補上,rownum又是10,也去掉,如果下去也就隻會顯示前面9條記錄了
2. 為什麼 rownum >1 時查不到一條記錄,而 rownum >0 或 rownum >=1 卻總顯示是以的記錄
因為 rownum 是在查詢到的結果集後加上去的,它總是從1開始
3. 為什麼 between 1 and 10 或者 between 0 and 10 能查到結果,而用 between 2 and 10 卻得不到結果
原因同上一樣,因為 rownum 總是從 1 開始
從上可以看出,任何時候想把 rownum = 1 這條記錄抛棄是不對的,它在結果集中是不可或缺的,少了rownum=1 就像空中樓閣一般不能存在,是以你的 rownum 條件要包含到 1
但如果就是想要用 rownum > 10 這種條件的話話就要用嵌套語句,把 rownum 先生成,然後對他進行查詢。
select * from (selet rownum as rn,t1.* from a where ...) where rn >10
一般代碼中對結果集進行分頁就是這麼幹的。
另外:rowid 與 rownum 雖都被稱為僞列,但它們的存在方式是不一樣的,rowid 可以說是實體存在的,表示記錄在表空間中的唯一位置ID,在DB中唯一。隻要記錄沒被搬動過,rowid是不變的。rowid 相對于表來說又像表中的一般列,是以以 rowid 為條件就不會有 rownum那些情況發生。
2、oracle的僞表
dual
該表主要目的是為了保證在使用SELECT語句中的語句的完整性而提供的。
---------------------------------------