熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

全面探討PL/SQL的復合數據類型

2013-11-13 15:33:52  來源: Oracle 

  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 stocksymbol%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 actiontimestampholding
  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 actiontimeampholding
  FROM portfolios
  WHERE account_nbr=
  ;
  BEGIN
  FOR xaction_rec in xactions_cur
  LOOP
  IF xactions_recholding=ORCL
  THEN
  notify_shareholder;
  END IF;
  END LOOP;
  使用記錄
  用戶可以給記錄賦值將值傳遞給其他程序記錄作為一種復合數據結構意味作他有兩個層次可用用戶可以引用整個記錄使用select into或fetch轉移所有域也可以將整個記錄傳遞給一個程序或將所有域的值賦給另一個記錄在更低的層次用戶可以處理記錄內單獨的域用戶可以給單獨的域賦值或者在單獨的域上運行布爾表達式也可以將一個或更多的域傳遞給另一個程序
  引用記錄
  記錄由域組成訪問記錄中的域使用點()符號我們使用上面的例子看看
  DELCARE
  TYPE stock_quote_rec IS RECORD
  (symbol stocksymbol%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
  asksize NUMBER
  last_tick VARCHAR()
  );
  real_time_detail detail_quote_rec;
  BEGIN
  real_time_detailbid_size:=;
  real_time_detailquotevolume:=;
  log_quote(real_time_detailquote);
  給記錄賦值
  給記錄或記錄中的域賦值的方法有幾種可以使用SELECT INTO或FETCH給整個記錄或單獨的域賦值 可以將整個記錄的值賦給其他記錄也可以通過給每個域賦值來得到記錄以下我們通過實例講解每一種賦值方法
  使用SELECT INTO
  使用SELECT INTO給記錄賦值要將記錄或域放在INTO子串中INTO子串中的變量與SELECT中列的位置相對應
  例
  DECLARE
  stock_info stocks%ROWTYPE;
  stock_info stocks%ROWTYPE;
  BEGIN
  SELECT symbolexchange
  INTO stock_infosymbolstock_infoexchange
  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 symbolexchangebegin_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 stockssymbol%TYPE
  bid NUMBER()
  ask number()
  volume NUMBER
  );
  TYPE stock_quote_too IS RECORD
  (symbol stockssymbol%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_onesymbol:=orcl;
  stock_onevolume:=;
  stock_two=stock_one;正確
  syock_also=stock_one;錯誤數據類型錯誤
  stock_alsosymbol:=stock_onesymbol;
  stock_alsovolume:=stock_onevolume; 
  記錄不能用於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/INTEGERSIGNTYPE和BOOLEAN其他的集合類型對數據庫的數據類型都有限制但Ind
From:http://tw.wingwit.com/Article/program/Oracle/201311/16925.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.