Oracle PL/SQL變得更快
更易於使用
特性集也更加豐富了
Oracle數據庫
g通過一系列有益的改進
繼續保持了PL/SQL在速度
簡單易用性和特性擴展方面的傳統優勢
這些改進包括
大大提高了執行速度
這要歸功於透明的性能改進
其中包括一個新的優化編譯器
更優的集成化本地編譯功能
以及幫助解決數字運算應用程序問題的新的數據類型
FORALL語句更加靈活
更加有用
例如
FORALL現在支持非連續索引
正則表達式以三個新函數(REGEXP_INSTR
REGEXP_REPLACE和REGEXP_SUBSTR)和用於比較的REGEXP_LIKE運算符的形式用於PL/SQL語言中
(要獲得更多信息
參見本期雜志中Jonathan Gennick撰寫的《一流的表達式》一文
)
集合得到了改進
包括比較集合是否相同
支持對嵌套表進行集合運算等
Oracle數據庫
g使PL/SQL繼續保持其作為Oracle數據庫的最高效
最富生產力的編程語言的地位
其在性能方面的大大提升
以及對IEEE算法和正則表達式的支持
如今完全開啟了將PL/SQL作為首選語言的新的功能領域
作為介紹Oracle數據庫
g中的PL/SQL系列文章的第一篇
本文將對Oracle數據庫
g中與集合相關的一些改進進行探討
比較集合 世紀
年代末期
當我首次對開發人員進行PL/SQL培訓的時候
很少有人使用(甚至知道)包(package)
而現在
很多人(包括我自己在內)都認為它是任何設計精良的PL/SQL應用程序的基礎
如今
打包軟件得到了廣泛使用
目前
非常重要但未得到充分利用的PL/SQL特性的前沿領域似乎就是集合的使用了
集合是Oracle中的數組
集合是一維列表
早在Oracle
中
就已經用到了集合(那時
稱作
PL/SQL表
)
但其功能及性能卻很有限
不過
Oracle後來的各個版本都對集合進行了改進
在Oracle數據庫
g中
這些數據結構對於幾乎所有的復雜PL/SQL應用程序項目來說都是強有力的
快速的和必不可少的
Oracle數據庫
g對集合的一個關鍵性改進是能夠比較兩個集合內容的相同之處(和不同之處)
在Oracle數據庫
g之前
你也可以對兩個集合進行比較
但必須為此編寫一個函數
編寫這樣的程序時需要考慮數個復雜因素
包括
必須為正在使用的各個集合類型分別編寫程序
即使兩個集合中的數據類型相同
但如果它們不是基於完全相同的類型定義的
你都需要使用不同的函數來進行比較
必須對表的內容進行逐行比較
這就意味著必須進行
全集合掃描
完成這一任務的代碼不是很復雜
但是
這一代碼冗長乏味
易於出錯
特別是比較諸如記錄
對象或者XMLType等復雜數據類型的集合時更是如此
你必須決定如何處理NULL
如果兩行都包含NULL
那麼它們相同嗎?Oracle認為
它們既不是相同
也不是不相同
但是
你的判斷可能會與此不同
你必須編寫代碼來處理這個問題
這種復雜性導致你不願意經常編寫這類程序
你甚至會在應用程序中回避編寫這類程序
在Oracle數據庫
g中
collcompare
sql文件包含了這類程序的一個示例
該程序是為基於employee表的記錄集合而編寫的
假設我在collcompare
sql腳本中安裝了emp_coll_pkg
equal函數
我可以按照如下方式來使用它
DECLARE
dbas emp_coll_pkg
employee_tt;
developers emp_coll_pkg
employee_tt;
BEGIN
populate_lists (dbas
developers);
IF emp_coll_pkg
equal (dbas
developers)
THEN
DBMS_OUTPUT
PUT_LINE (
Likely a very small IT organization!
);
END IF;
END;
這段代碼簡單明了
可讀性好
(你不用再經歷編寫此類函數的痛苦過程多好啊!)為了讓你工作更輕松
Oracle數據庫
g現在允許你對兩個嵌套表進行
原始
比較(native compare)了
換句話說
你不必再編寫任何特定於集合的比較邏輯
而可以直接進行比較
如下所示
DECLARE
dbas emp_coll_pkg
employee_tt;
developers emp_coll_pkg
employee_tt;
BEGIN
populate_lists (dbas
developers);
IF dbas = developers
THEN
DBMS_OUTPUT
PUT_LINE (
Likely a very small IT organization!
);
END IF;
END;
在這種情況下
集合比較僅適用於嵌套表
換句話說
你還不能直接比較兩個關聯數組(過去稱作
索引表
)或者變長數組的內容
希望Oracle數據庫的下一版本會增加關聯數組和變長數組的比較功能
集合理論與Multiset Union運算 SQL語言很久以前就提供了將集合運算(UNION
INTERSECT和MINUS)用於查詢結果集的功能
如今在Oracle數據庫
g中
你可以對PL/SQL程序中的嵌套表(且僅限於嵌套表)和在關系表中聲明為列的嵌套表使用上述功能強大的高級運算符
現在我們從UNION開始
看看這樣做所需的一些語法
首先
我創建一個模式級別的嵌套表類型
CREATE OR REPLACE TYPE strings_nt
IS TABLE OF VARCHAR
(
);
/
然後
我定義一個包
在該包中
我創建並填充兩個此種類型的嵌套表
每個嵌套表都包含一些我和我父親最喜歡的東西
CREATE OR REPLACE PACKAGE favorites_pkg
IS
my_favorites strings_nt
:= strings_nt (
CHOCOLATE
BRUSSEL SPROUTS
SPIDER ROLL
);
dad_favorites strings_nt
:= strings_nt (
PICKLED HERRING
POTATOES
PASTRAMI
CHOCOLATE
);
PROCEDURE show_favorites (
title_in IN VARCHAR
favs_in IN strings_nt
);
END;
/
在該包中
我還創建了一個用於顯示strings_nt 嵌套表內容的過程
下面很快就會用到它
通過在任意程序外的包中定義這些集合
這些集合在我的對話期間會一直保持不變(保持其狀態和值)
直到我將更改或刪除它們為止
這就是說
現在我可以在包外編寫程序來對這些集合的內容進行操作了
注意
出於介紹集合功能的目的
我對該包進行了簡化
在生產應用程序中
你應該時刻注意
隱藏
包主體中的包數據(如同這些集合一樣)
然後提供過程和函數來管理這些數據
例如
假設我想把這兩個集合合並成一個
我們的最愛
的集合
在Oracle數據庫
g出現以前
我必須編寫一個將一個集合的內容轉移到另一個集合的循環
而現在
我可以依賴MULTISET UNION運算符來實現這一點了
如下所示
DECLARE
our_favorites
strings_nt := strings_nt ();
BEGIN
our_favorites :=
favorites_pkg
my_favorites
MULTISET UNION
favorites_pkg
dad_favorites;
favorites_pkg
show_favorites (
ME then DAD
our_favorites);
END;
/
此腳本的輸出結果為
ME then DAD
= CHOCOLATE
= BRUSSEL SPROUTS
= SPIDER ROLL
= PICKLED HERRING
= POTATOES
= PASTRAMI
= CHOCOLATE
可以看出
兩個嵌套表的值被合並到一起了
而且立刻就可以看到
MULTISET UNION運算符不同於SQL UNION運算符(實際上
與SQL的UNION ALL運算符完全相同)
對兩個SELECT結果集進行UNION運算時
SQL引擎會自動生成一個惟一的有序結果集
換句話說
如果我的兩個嵌套表都是查詢
那麼UNION將生成這樣的結果集
BRUSSEL SPROUTS
CHOCOLATE
PASTRAMI
PICKLED HERRING
POTATOES
SPIDER ROLL
這些數據是按照字母順序排列的
且CHOCOLATE僅出現一次
為什麼會產生不同的結果呢?因為嵌套表是一種多集合(multiset)
m/l 對其做了如下定義
一種類似於集合的對象
在其內部
順序沒有意義
而多重性卻具有明確的意義
因此
多集合{
}和{
}是等同的
而{
}和{
}卻是不同的
Oracle文件中說
嵌套表和變長數組的區別在於嵌套表列中存儲的數據不保存其順序
而在變長數組中存儲的數據保存其順序
在Oracle數據庫
g之前
這種區別在PL/SQL中沒多大意義
現在
有了集合運算符之後
多集合(或嵌套表)的特性便顯得極為重要了
為了更好地理解嵌套表數據沒有順序
MULTISET UNION也不會對結果嵌套表應用順序這一特性
請我們來看看面的這個程序塊
DECLARE
our_favorites
strings_nt := strings_nt ();
BEGIN
our_favorites :=
favorites_pkg
dad_favorites
MULTISET UNION
favorites_pkg
my_favorites;
favorites_pkg
show_favorites (
DAD then ME
our_favorites);
END;
/
與前面的程序塊惟一不同的是
我改變了MULTISET UNION運算中嵌套表的順序
結果就變為
DAD then ME
= PICKLED HERRING
= POTATOES
= PASTRAMI
= CHOCOLATE
= CHOCOLATE
= BRUSSEL SPROUTS
= SPIDER ROLL
如果你不希望合並之後的嵌套表中出現重復項
那麼可
From:http://tw.wingwit.com/Article/program/Oracle/201311/18364.html