PL/SQL七复合数据结构
生活随笔
收集整理的這篇文章主要介紹了
PL/SQL七复合数据结构
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
PL/SQL有兩種復合數據結構:記錄和集合。記錄由不同的域組成,集合由不同的元素組成。 記錄: 記錄是PL/SQL的一種復合數據結構,scalar數據類型和其他數據類型只是簡單的在包一級進行預定義,但復合數據類型在使用前必須被定義,記錄之所以被稱為復合數據類型是因為他由域這種由數據元素的邏輯組所組成。域可以是scalar數據類型或其他記錄類型,它與c語言中的結構相似,記錄也可以看成表中的數據行,域則相當于表中的列,在表和虛擬表(視圖或查詢)中非常容易定義和使用,行或記錄中的每一列或域都可以被引用或單獨賦值,也可以通過一個單獨的語句引用記錄所有的域。在存儲過程或函數中記錄也可能有參數。 創建記錄:顯示定義和隱式定義;一旦記錄被定義后,聲明或創建定義類型的記錄變量,然后才是使用該變量。隱式聲明是在基于表的結構或查詢上使用%TYPE屬性,隱式聲明是一個更強有力的工具,這是因為數據變量是動態創建的 顯示定義:顯示定義記錄是在PL/SQL程序塊中創建記錄變量之前的聲明部分定義: TYPE record_type IS RECORD(field_definition_list); Field_definition_list是由逗號分隔的列表,語法如下: Field_name data_type_and_size [NOT NULL][{:=|DEFAULT} default_value] DECLARE TYPE stock_quote_rec IS RECORD (symbol stock.symbol %TYPE, bid NUMBER(10, 4), ask NUMBER(10, 4), volumn NUMBER NOT NULL:=0, exchange VARCHAR2(6) DEFAULT 'NASDAQ' ); real_time_quote stock_quote_rec; variable 域定義時的%TYPE屬性用于引用數據庫中的表或視圖的數據類型和大小,而在此之前程序不知道類型和大小。在上面的例子中記錄域在編譯時將被定義為與列SYMBOL相同的數據類型和大小,當代碼中要使用來自數據庫中的數據時,在變量或域定義中最好使用%TYPE來定義。 隱士定義:我們不用描述記錄的每一個域,這是因為我們不需要定義記錄的結構,不需要使用TYPE,相反在生命記錄變量時用%ROWTYPE命令定義與數據庫表,試圖,游標有相同結構的記錄,與TYPE命令相同的是它是一種定義獲得數據庫記錄的好方法。 CURSOR xactions_cur(acct_no IN VARCHAR2) IS SELECT action, timestamp, holding FROM portfolios WHERE account_nbr = 'acct_no';xaction_info xactions_cur%ROWTYPE; variableDECLARE CURSOR xactionS_cur IS SELECT action, timestamp, holding FROM portfolios WHERE account_nbr = '37';BEGIN FOR xaction_rec in xactions_cur LOOP IF xaction_rec.holding = 'orcl' THEN notify_shareholder; END IF END LOOP; END 使用記錄: 用戶可以給記錄賦值、將值傳遞給其他程序。記錄作為一種復合數據結構意味作他有兩個層次可用。用戶可以引用整個記錄,使用select into或fetch轉移所有域,也可以將整個記錄傳遞給一個程序或將所有域的值賦給另一個記錄。在更低的層次,用戶可以處理記錄內單獨的域,用戶可以給單獨的域賦值或者在單獨的域上運行布爾表達式,也可以將一個或更多的域傳遞給另一個程序。 引用記錄:記錄由域組成,訪問記錄中的域使用點(.)符號,我們使用上面的例子看看 DECLARE TYPE stock_quote_rec IS RECORD( symbol stock.symbol%TYPE, bid NUMBER(10, 4), ask NUMBER(10, 4), volumn NUMBER NOT NULL := 0, exchange VARCHAR2(6) DEFAULT 'NASDQA' );TYPE detailed_quote_rec IS RECORD( quote stock_quote_rec, timestamp DATE, bid_size NUMBER, ask_size NUMBER, last_tick VARCHAR2(4) );real_time_detail detail_quote_rec;BEGIN real_time_detail.bin_size:=1000; real_time_detail.quote.volumn:=156700; log_quote(real_time_detail.quote); 給記錄賦值: 使用SELECT INTO: 使用SELECT INTO給記錄賦值要將記錄或域放在INTO子串中,INTO子串中的變量與SELECT中列的位置相對應。 DECLARE stock_info1 stocks%ROWTYPE; stock_info2 stocks%ROWTYPE; BEGIN SELECT symbol, exchange INTO stock_info1.symbol, stock_info1.exchange FROM stocks WHERE symbol = 'ORCL';SELECT * INTO stock_info2 FROM stocks WHERE symbol = 'ORCL'; END 使用FETCH: 如果SQL語句返回多行數據或者希望使用帶參數的游標,那么就要使用游標,這種情況下使用FETCH語句代替INSTEAD INTO是一個更簡單、更有效率的方法,但在安全性較高的包中FETCH的語法如下: FETCH cursor_name INTO variable; DECLARE CURSOR stock_cur(symbol_in VARCHAR2) IS SELECT symbol, exchange, begin_date FROM stock WHERE symbol = UPPER(symbol_in);stock_info stock_cur%ROWTYPEBEGIN OPEN stock_cur('ORCL'); FETCH stock_cur INTO stock_info; 使用賦值語句將整個記錄復制給另一個記錄是一項非常有用的技術,不過記錄必須精確地被聲明為相同的類型,不能是基于兩個不同的TYPE語句來獲得相同的結構。 DECLARE TYPE stock_quote_rec IS RECORD( symbol stocks.symbols%TYPE, bid NUMBER(10, 4), ask NUMBER(10, 4), volumn NUMBER ); TYPE stock_quote_too IS RECORD( symbol stocks.symbols%TYPE, bid NUMBER(10, 4), ask NUMBER(10, 4), volumn NUMBER ); stock_one stocks_quote_rec; stock_two stocks_quote_rec;stock_also stock_rec_too;BEGIN stock_one.symbol:='orcl'; stock_one.volumn:=12334400; stock_two:=stock_one; // correct stock_also:=stock_one; // incorrect, the data type is wrong stock_also.symbol:=stock_one.symbol; stock_also.volumn:=stock_one.volumn; END 記錄不能用于INSERT語句和將記錄直接用于比較,下面兩種情況是錯誤的: INSERT INTO stocks VALUES(stock_record); IF stock_rec1 > stock_rec2 THEN 集合:集合與其他語言中的數組相似,在ORACLE7.3及以前的版本中只有一種集合稱為PL/SQL表,這種類型的集合依然保留,就是索引(INDEX_BY)表,與記錄相似,集合在定義的時候必須使用TYPE語句,然后才是創建和使用這種類型的變量 集合的類型:index_by表,嵌套表,VARRAY。這三種類型的集合之間由許多差異,包括數據綁定、稀疏性(sparsity)、數據庫中的存儲能力都不相同。綁定涉及到集合中元素數量的限制,VARRAY集合中的元素的數量是有限,Index_by和嵌套表則是沒有限制的。稀疏性描述了集合的下標是否有間隔,Index_by表總是稀疏的,如果元素被刪除了嵌套表可以是稀疏的,但VARRAY類型的集合則是緊密的,它的下標之間沒有間隔。 Index_by表不能存儲在數據庫中,但嵌套表和VARRAY可以被存儲在數據庫中。 雖然這三種類型的集合有很多不同之處,但他們也由很多相似的地方: ·???????? 都是一維的類似數組的結構 ·???????? 都有內建的方法 ·???????? 訪問由點分隔 集合的創建: Index_by TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY BINRAY_INTEGER; Eg. DECLARE TYPE symbol_tab_typ IS TABLE OF VARCHAR2(5) INDEX BY BINARY_INTEGER; symbol_tab symbol_tab_typ; BEGIN 嵌套表:嵌套表非常類似于Index_by表,創建的語法也非常相似。使用TYPE語句,只是沒有INDEX BY BINARY_INTEGER子串 TYPE type_name IS TABLE OF element_type [NOT NULL] VARRAY: TYPE type_name IS [VARRAY|VARRAYING] (max_size) OF element_type [NOT NULL] 使用集合:像記錄一樣,集合可以在兩個層面上使用 o??? 操作整個集合 o??? 訪問集合中的 單個元素 第一種情況使用集合名,第二種情況使用下標collection(subscript) 初始化、刪除、引用集合: 使用集合之前必須要初始化,對于Index_by表初始化是自動進行的,但是對于嵌套表和VARRAY就必須使用內建的構造函數。如果重新調用,嵌套表和VARRAY自動置NULL,這不只是元素置NULL,而是整個集合置NULL。給集合內的元素賦值需要使用下標符號。將一個集合的值賦給另一個集合,只需要簡單的使用賦值操作符 Index_by: DECLARE TYPE symbol_tab_typ IS TABLE OF VARCHAR2(5) INDEX BY BINARY_INTEGER; TYPE account_tab_typ IS TABLE OF accounts%ROWTYPE INDEX BY BINARY_INTEGER; symbol_tab symbol_tab_typ; account_tab account_tab_typ; new_acct_tab account_tab_typ; BEGIN SELECT * INTO account_tab(147) FROM accounts WHERE account_nbr = 147; SELECT * INTO account_tab(-3) FROM accounts WHERE account_nbr = 3003; IF account_tab(147).balance < 500 THEN change_maintenance_fee(147); END IF new_acct_tab:=account_tab; symbol_tab(1):='ORCL'; symbol_tab(2):='CSCO'; symbol_tab(3):='SUN';publish_portfolio(symbol_tab); 嵌套表和VARRAY:構造函數初始化,構造函數和集合的名字相同,同時有一組參數,每個參數對應一個元素,如果參數為NULL,那么對應的元素就被初始化為NULL,如果創建了元素,但沒有填充數據,那么元素將保持null值,可以被引用,但不能保持數據。如果元素沒有初始化,那么就不能引用該元素。 DECLARE TYPE stock_list IS TABLE OF stock.symbol%TYPE; TYPE top10_list IS VARRAY(10) OF stock.symbol%TYPE; biotech_stocks stock_list; tech_10 top10_list;BEGIN biotech_stocks(1):='AMGN'; // this is illegal, becuase biotech_stocks do not been initialize IF biotech_stocks IS NULL THEN biotech_stocks:=('AMGN', 'BGEN', 'IMCL', 'GERN', 'CAR'); END IF;tech_10:=top10_list('ORCL', 'CSCO', 'MSFT', 'INTC', 'SUNW', 'IBM', NULL, NULL); IF tech_10(7) IS NULL THEN tech_10(7):='CPQ'; END IF tech_10(8):='DELL'; END 在這個例子中,嵌套表BIOTECH_STOCKS初始化有5個元素,VARRAY tech_10集合最多能有10 個元素,但構造函數只創建了8個元素,其中還有兩個元素是NULL值,在程序中給他們賦值。 初始化基于記錄的集合,就必須將記錄傳遞給構造函數,注意不能只是簡單的將記錄的域傳遞給構造函數。例如: DECLARE TYPE stock_quote_rec IS RECORD( symbol stock.symbol%TYPE, bid NUMBER(10, 4), ask NUMBER(10, 4), volumn NUMBER NOT NULL:=0 ); TYPE stock_tab_typ IS TABLE OF stock_quote_rec; quote_list stock_tab_typ; single_quote stock_quote_rec;BEGIN single_quote.symbol:='OPCL'; single_quote.bid:=100; single_quote.ask:=101; single_quote.volumn:=230000; quote_list:=stock_tab_typ(single_quote); // legal quote_list:=stock_tab_typ('CSCO', 43, 323, 323000); // illegal DBMS_OUTPUT.LINE(quote_list(1).bid); END 集合的方法:除了構造函數外,集合還有很多內建函數,這些函數稱為方法。調用方法的語法如下:collection.method,下面為oracle中集合的方法:| 方法 | 描述 | 使用限制 |
| COUNT | 返回集合中元素的個數 | ? |
| DELETE | 刪除集合中所有元素 | ? |
| DELETE() | 刪除元素下標為x的元素,如果x為null,則集合保持不變 | 對VARRAY非法 |
| DELETE(,) | 刪除元素下標從X到Y的元素,如果X>Y集合保持不變 | 對VARRAY非法 |
| EXIST() | 如果集合元素x已經初始化,則返回TRUE, 否則返回FALSE | ? |
| EXTEND | 在集合末尾添加一個元素 | 對Index_by非法 |
| EXTEND() | 在集合末尾添加x個元素 | 對Index_by非法 |
| EXTEND(,) | 在集合末尾添加元素n的x個副本 | 對Index_by非法 |
| FIRST | 返回集合中的第一個元素的下標號,對于VARRAY集合始終返回1。 | ? |
| LAST | 返回集合中最后一個元素的下標號, 對于VARRAY返回值始終等于COUNT. | ? |
| LIMIT | 返回VARRY集合的最大的元素個數,對于嵌套表和對于嵌套表和Index_by為null | Index_by集合無用 |
| NEXT() | 返回在元素x之后及緊挨著它的元素的值,如果該元素是最后一個元素,則返回null. | ? |
| PRIOR() | 返回集合中在元素x之前緊挨著它的元素的值,如果該元素是第一個元素,則返回null。 | ? |
| TRIM | 從集合末端開始刪除一個元素 | 對于index_by不合法 |
| TRIM() | 從集合末端開始刪除x個元素 | 對index_by不合法 |
轉載于:https://www.cnblogs.com/garinzhang/archive/2012/06/27/2566511.html
總結
以上是生活随笔為你收集整理的PL/SQL七复合数据结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 技术驱动还是产品驱动
- 下一篇: FPGA模拟串口发送功能的Verilog