PL/SQL有兩種復合數據結構
記錄和集合
記錄由不同的域組成
集合由不同的元素組成
在本文中我們將討論記錄和集合的類型
怎樣定義和使用記錄和集合
PL/SQL 記錄
記錄是PL/SQL的一種復合數據結構
scalar數據類型和其他數據類型只是簡單的在包一級進行預定義
但復合數據類型在使用前必須被定義
記錄之所以被稱為復合數據類型是因為他由域這種由數據元素的邏輯組所組成
域可以是scalar數據類型或其他記錄類型
它與c語言中的結構相似
記錄也可以看成表中的數據行
域則相當於表中的列
在表和虛擬表(視圖或查詢)中非常容易定義和使用
行或記錄中的每一列或域都可以被引用或單獨賦值
也可以通過一個單獨的語句引用記錄所有的域
在存儲過程或函數中記錄也可能有參數
創建記錄
在PL/SQL中有兩種定義方式
顯式定義和隱式定義
一旦記錄被定義後
聲明或創建定義類型的記錄變量
然後才是使用該變量
隱式聲明是在基於表的結構或查詢上使用%TYPE屬性
隱式聲明是一個更強有力的工具
這是因為這種數據變量是動態創建的
顯式定義記錄
顯式定義記錄是在PL/SQL程序塊中創建記錄變量之前在聲明部分定義
使用type命令定義記錄
然後在創建該記錄的變量
語法如下
TYPE record_type IS RECORD (field_definition_list);
field_definition_list是由逗號分隔的列表
域定義的語法如下
field_name data_type_and_size [NOT NULL][{:=|DEFAULT} default_value]
域名必須服從與表或列的命名規則相同的命名規則
下面我們看一個例子
DELCARE
TYPE stock_quote_rec IS RECORD
(symbol stock
symbol%TYPE
bid NUMBER(
)
ask NUMBER(
)
volume NUMBER NOT NULL:=
exchange VARCHAR
(
) DEFAULT
NASDAQ
);
real_time_quote stock_quote_rec;
variable
域定義時的%TYPE屬性用於引用數據庫中的表或視圖的數據類型和大小
而在此之前程序不知道類型和大小
在上面的例子中記錄域在編譯時將被定義為與列SYMBOL相同的數據類型和大小
當代碼中要使用來自數據庫中的數據時
在變量或域定義中最好使用%TYPE來定義
隱式定義記錄
隱式定義記錄中
我們不用描述記錄的每一個域
這是因為我們不需要定義記錄的結構
不需要使用TYPE語句
相反在聲明記錄變量時使用%ROWTYPE命令定義與數據庫表
視圖
游標有相同結構的記錄
與TYPE命令相同的是它是一種定義獲得數據庫數據記錄的好方法
DECLARE
accounter_info accounts%ROWTYPR;
CURSOR xactions_cur(acct_no IN VARCHAR
) IS
SELECT action
timestamp
holding
FROM portfolios
WHERE account_nbr=
acct_no
;
xaction_info xactions_cur%ROWTYPE;
variable
有一些PL/SQL指令在使用隱式定義記錄時沒有使用%ROWTYPE屬性
比如游標FOR循環或觸發器中的:old和:new記錄
DELCARE
CURSOR xaction_cur IS
SELECT action
timeamp
holding
FROM portfolios
WHERE account_nbr=
;
BEGIN
FOR xaction_rec in xactions_cur
LOOP
IF xactions_rec
holding=
ORCL
THEN
notify_shareholder;
END IF;
END LOOP;
使用記錄
用戶可以給記錄賦值
將值傳遞給其他程序
記錄作為一種復合數據結構意味作他有兩個層次可用
用戶可以引用整個記錄
使用select into或fetch轉移所有域
也可以將整個記錄傳遞給一個程序或將所有域的值賦給另一個記錄
在更低的層次
用戶可以處理記錄內單獨的域
用戶可以給單獨的域賦值或者在單獨的域上運行布爾表達式
也可以將一個或更多的域傳遞給另一個程序
引用記錄
記錄由域組成
訪問記錄中的域使用點(
)符號
我們使用上面的例子看看
DELCARE
TYPE stock_quote_rec IS RECORD
(symbol stock
symbol%TYPE
bid NUMBER(
)
ask NUMBER(
)
volume NUMBER NOT NULL:=
exchange VARCHAR
(
) DEFAULT
NASDAQ
);
TYPE detailed_quote_rec IS RECORD
(quote stock_quote_rec
timestamp date
bid_size NUMBER
ask
size NUMBER
last_tick VARCHAR
(
)
);
real_time_detail detail_quote_rec;
BEGIN
real_time_detail
bid_size:=
;
real_time_detail
quote
volume:=
;
log_quote(real_time_detail
quote);
給記錄賦值
給記錄或記錄中的域賦值的方法有幾種
可以使用SELECT INTO或FETCH給整個記錄或單獨的域賦值
可以將整個記錄的值賦給其他記錄
也可以通過給每個域賦值來得到記錄
以下我們通過實例講解每一種賦值方法
使用SELECT INTO
使用SELECT INTO給記錄賦值要將記錄或域放在INTO子串中
INTO子串中的變量與SELECT中列的位置相對應
例
DECLARE
stock_info
stocks%ROWTYPE;
stock_info
stocks%ROWTYPE;
BEGIN
SELECT symbol
exchange
INTO stock_info
symbol
stock_info
exchange
FROM stocks
WHERE symbol=
ORCL
;
SELECT * INTO stock_info
FROM stocks
WHERE symbol=
ORCL
;
使用FETCH
如果SQL語句返回多行數據或者希望使用帶參數的游標
那麼就要使用游標
這種情況下使用FETCH語句代替INSTEAD INTO是一個更簡單
更有效率的方法
但在安全性較高的包中FETCH的語法如下
FETCH cursor_name INTO variable;
我們改寫上面的例子
DECLARE
CURSOR stock_cur(symbol_in VARCHAR
) IS
SELECT symbol
exchange
begin_date
FROM stock
WHERE symbol=UPPER(symbol_in);
stock_info stock_cur%ROWTYPE
BEGIN
OPEN stock_cur(
ORCL
);
FETCH stock_cur INTO stock_info;
使用賦值語句將整個記錄復制給另一個記錄是一項非常有用的技術
不過記錄必須精確地被聲明為相同的類型
不能是基於兩個不同的TYPE語句來獲得相同的結構
例
DECLARE
TYPE stock_quote_rec IS RECORD
(symbol stocks
symbol%TYPE
bid NUMBER(
)
ask number(
)
volume NUMBER
);
TYPE stock_quote_too IS RECORD
(symbol stocks
symbol%TYPE
bid NUMBER(
)
ask number(
)
volume NUMBER
);
這兩個記錄看上去是一樣的
但實際上是不一樣的
stock_one stocks_quote_rec;
stock_two stocks_quote_rec;
這兩個域有相同的數據類型和大小
stock_also stock_rec_too
與stock_quote_rec是不同的數據類型
BEGIN
stock_one
symbol:=
orcl
;
stock_one
volume:=
;
stock_two
=stock_one;
正確
syock_also
=stock_one;
錯誤
數據類型錯誤
stock_also
symbol:=stock_one
symbol;
stock_also
volume:=stock_one
volume;
記錄不能用於INSERT語句和將記錄直接用於比較
下面兩種情況是錯誤的
INSERT INTO stocks VALUES (stock_record);
和
IF stock_rec
>stock_rec
THEN
要特別注意考試中試題中有可能用%ROWTYPE來欺騙你
但這是錯誤的
記住這一點
還有可能會出現用記錄排序的情況
ORACLE不支持記錄之間的直接比較
對於記錄比較
可以采用下面的兩個選擇
設計一個函數
該函數返回scalar數據類型
使用這個函數比較記錄
如
IF sort_rec(stock_one)>sort_rec(stock_two) THEN
可以使用數據庫對象
數據庫對象可以使用order或map方法定義
允許oracle對復合數據類型進行比較
關於數據庫對象的討論已經超越了本文的范圍
要詳細了解數據庫對象
可以查閱oracle手冊
PL/SQL集合
集合與其他語言中的數組相似
在ORACLE
及以前的版本中只有一種集合稱為PL/SQL表
這種類型的集合依然保留
就是索引(INDEX_BY)表
與記錄相似
集合在定義的時候必須使用TYPE語句
然後才是創建和使用這種類型的變量
集合的類型
PL/SQL有三種類型的集合
Index_by表
嵌套表
VARRAY
這三種類型的集合之間由許多差異
包括數據綁定
稀疏性(sparsity)
數據庫中的存儲能力都不相同
綁定涉及到集合中元素數量的限制
VARRAY集合中的元素的數量是有限
Index_by和嵌套表則是沒有限制的
稀疏性描述了集合的下標是否有間隔
Index_by表總是稀疏的
如果元素被刪除了嵌套表可以是稀疏的
但VARRAY類型的集合則是緊密的
它的下標之間沒有間隔
Index_by表不能存儲在數據庫中
但嵌套表和VARRAY可以被存儲在數據庫中
雖然這三種類型的集合有很多不同之處
但他們也由很多相似的地方
都是一維的類似數組的結構
都有內建的方法
訪問由點分隔
Index_by表
Index_by表集合的定義語法如下
TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX
BY BINARY_INTERGET;
這裡面重要的關鍵字是INDEX BY BINARY_INTERGET
沒有這個關鍵字
那麼集合將是一個嵌套表
element_type可以是任何合法的PL/SQL數據類型
包括
PLS/INTEGER
SIGNTYPE
和BOOLEAN
其他的集合類型對數據庫的數據類型都有限制
但Ind
From:http://tw.wingwit.com/Article/program/Oracle/201311/16925.html