Oracle11G新特性——虛擬列

打算寫一系列的文章介紹11g的新特性和變化。

Oracle11g增加了表的虛擬列,這個列的數據並沒有存儲在數據文件中,而是Oracle通過列數據的生成放到了數據字典中。

 

看一個簡單的虛擬列的例子:

SQL> CREATE OR REPLACE FUNCTION F_GETTYPE(P_TYPE IN VARCHAR2) RETURN NUMBER
2 DETERMINISTIC AS
3 BEGIN
4 IF P_TYPE IN ('TABLE', 'INDEX', 'LOB', 'TABLE PARTITION', 'INDEX PARTITION', 'LOB PARTITION',

5 'TABLE SUBPARTITON', 'INDEX SUBPARTITION', 'LOB SUBPARTITION', 'CLUSTER') THEN
6 RETURN 1;
7 ELSE
8 RETURN 0;
9 END IF;
10 END;
11 /

函數已創建。

SQL> CREATE TABLE T_VIRTUAL_COLUMN
2 (
3 ID NUMBER PRIMARY KEY,
4 V_LENGTH AS (CEIL(LENGTH(TO_CHAR(ID)) / 2) 1 LENGTH(NAME) LENGTH(TYPE)),
5 NAME VARCHAR2(30),
6 V_NAME CHAR(50) GENERATED ALWAYS AS (LOWER(NAME)) VIRTUAL,
7 TYPE VARCHAR2(30),
8 V_TYPE AS (F_GETTYPE(TYPE))
9 );

表已創建。

上面例子中,V_LENGTHV_NAMEV_TYPE都是虛擬列,虛擬列的數值是通過真實列中的數據計算而來的。

虛擬列的位置可以放在它參考的列的前面,也可以包括多個實際列的值,但是不能引用其他的虛擬列:

SQL> CREATE TABLE T_VIRTUAL_COLUMN_ERR
2 (ID NUMBER,
3 V_ID1 AS (ID * 5),
4 V_ID2 AS (V_ID1 45)
5 );
V_ID1 AS (ID * 5),
*
3 行出現錯誤:
ORA-54012:
在列表達式中引用了虛擬列

虛擬列的完整寫法如上面例子中V_NAME列,包括列名、數據類型、GENERATED ALWAYS關鍵字、AS加列表達式和VIRTUAL關鍵字。其中GENERATED ALWAYSVIRTUAL爲可選關鍵字,主要用於描述虛擬列的特性,寫與不寫沒有本質區別。而列的數據類型如果忽略,那麼Oracle會根據AS後面的表達式最終結果的數據類型來確定虛擬列的數據類型。

虛擬列可以使用Oracle自帶的函數,也可以使用用戶定義的函數,不過對於用戶定義的函數要求必須聲明函數的確定性:

SQL> CREATE OR REPLACE FUNCTION F_TEST RETURN NUMBER AS
2 BEGIN
3 RETURN 1;
4 END;
5 /

函數已創建。

SQL> CREATE TABLE T_VIRTUAL_COLUMN_DETER
2 (ID NUMBER, VID AS (F_TEST));
(ID NUMBER, VID AS (F_TEST))
*
2 行出現錯誤:
ORA-54016:
指定了無效的列表達式

IXDBA.NET社區論壇

虛擬列必須是對實際列進行操作後的結果,不能像上面這樣直接寫一個返回常數的函數,換句話說,表不能只包括虛擬列:

SQL> CREATE OR REPLACE FUNCTION F_TEST(P_IN IN NUMBER) RETURN NUMBER AS
2 BEGIN
3 RETURN 1;
4 END;
5 /

函數已創建。

SQL> CREATE TABLE T_VIRTUAL_COLUMN_DETER
2 (
3 ID NUMBER,
4 V_ID AS (F_TEST(ID))
5 );
V_ID AS (F_TEST(ID))
*
4 行出現錯誤:
ORA-30553:
函數不能確定

現在錯誤信息顯示,函數沒有聲明確定性:

SQL> CREATE OR REPLACE FUNCTION F_TEST(P_IN IN NUMBER) RETURN NUMBER DETERMINISTIC AS
2 BEGIN
3 RETURN 1;
4 END;
5 /

函數已創建。

SQL> CREATE TABLE T_VIRTUAL_COLUMN_DETER
2 (
3 ID NUMBER,
4 V_ID AS (F_TEST(ID))
5 );

表已創建。

Oracle雖然在創建創建的時候會檢查函數的確定性,在表建立之後,卻可以將函數替換爲非確定性函數:

SQL> INSERT INTO T_VIRTUAL_COLUMN_DETER (ID) VALUES (1);

已創建 1 行。

SQL> SELECT * FROM T_VIRTUAL_COLUMN_DETER;

ID V_ID
---------- ----------
1 1

SQL> DROP FUNCTION F_TEST;

函數已刪除。

SQL> SELECT * FROM T_VIRTUAL_COLUMN_DETER;
SELECT * FROM T_VIRTUAL_COLUMN_DETER
*
1 行出現錯誤:
ORA-00904: "YANGTK"."F_TEST":

標識符無效

發佈了30 篇原創文章 · 獲贊 3 · 訪問量 42萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章