oracle存儲過程中的變量


  通過學習,了解到了變量的一些知識。
變量的分類如下:

存儲過程中的變量:
一、標量類型 (有%TYPE)
二、復合類型
     (1)記錄類型 (有%ROWTYPE)
     (2)索引表類型(關聯數組)
     (3)varry變長數組

一、標量類型
  標量類型,一種是常用的有NUMBER、CHAR 、VARCHAR2 、VARCHAR、NCHAR 、NVARCHAR2 、LONG 、DATE 、TIMESTAMP ,基本上oracle 數據庫認識的類型都可以直接用了。
  還有一些我覺得不常用的,PLS_INTEGER 、BINARY_INTEGER 、SIMPLE_INTEGER 、布爾類型(可以用來存儲邏輯的值,不能用作定義表中的數據類型)。
  另外還有一個最常用的 %TYPE 。
  因為上一篇已經簡單用過第一種,所以這里介紹一下%TYPE 。
  %TYPE 這種方式定義的變量類型的方式和其他的有所不同,它利用已經存在的數據類型來定義新數據的數據類型。例如,當定義多個變量或常量時,只要前面使用過的數據類型,后邊的變量就可以利用%TYPE 引用,最常見的就是把表中的字段類型作為變量或常量的數據類型。使用此種方式的好處有以下幾點:

利用%TYPE 方式定義的變量類型和被引用的常量數據類型保持一致,如果以前是VARCHAR 類型,現在要改成NUMBER 類型,那就只需要直接改數據表中的類型即可,對已寫好的存儲過程 沒有影響。
還有個好處就是,存儲過程 基本都會有表操作,這就避免了在數據傳入的時候,引發數據溢出或不符的情況。比如數據庫里是VARCHAR(1) 這樣的,但是實際傳入的可能是張三 這樣的字符串,肯定會導致在執行到這行數據的時候引發異常。如果能用%TYPE,那在調用存儲過程 的時候,就能拋出錯誤。
如下圖所示:
  sex LY_DS.LY_NB%TYPE ,表示:
  定義一個變量sex,它的類型與表LY_DS中的字段LY_NB` 類型一致。

1 create or replace procedure test_select_procedure
2 (sex  LY_DS.LY_NB%TYPE,countNum out number)
3 AS
4 BEGIN
5 select count(*) into countNum from ly_ds where LY_NB=sex;
6 dbms_output.put_line(countNum);
7 END;

二、復合類型

1、記錄類型

  如果在存儲過程中查詢結果中,是多列的情況,我們可能需要查詢到結果后,對其做引用名稱.成員名稱 這樣取值。上一篇中說到過,可以使用into,即如下寫法

 1 create or replace procedure test_select2_procedure
 2 (sex  varchar)
 3 AS
 4 countNum number(10); --別忘了寫上具體的長度,並且以分號結束
 5 maxId number(10); --別忘了寫上具體的長度,並且以分號結束
 6 BEGIN
 7 select count(*),max(id) into countNum,maxId from ly_ds where LY_NB=sex;
 8 dbms_output.put_line(countNum);
 9 dbms_output.put_line(maxId);
10 END;

上邊的是一種寫法,就是into 后邊跟上定義好的多個標量類型 。但是如果字段很多呢?
  顯而易見,再用這個into 就不合適了,記錄類型 就是解決這個的。

(1)定義type 的聲明寫法
  定義type 的寫法為 type type_name is record(col_name col_type); 這樣,括號里可以寫多個,中間用 , 分割,但最后一個不能有 , ,具體如下:

 1 set serveroutput on;
 2 DECLARE
 3 TYPE thomas IS RECORD   --以TYPE type_name IS RECORD開始   --此處thomas是個變量類型
 4 (
 5    v_ly_nl test.name%TYPE,
 6    v_ly_mc varchar(100) --最后不要加,   
 7 );  --最后以 ;結束
 8 v_obj thoams; --將新對象定義為剛才聲明的類型    --給thomas這個變量實例化了一個名字叫v_obj
 9 BEGIN
10  --into賦值給v_obj,會按照定義的type順序賦值
11 select id,nameinto v_obj from test where id='2'; 
12 dbms_output.put_line('第一個變量:'||v_obj.v_ly_nl);
13 dbms_output.put_line('第二個變量:'||v_obj.v_ly_mc);
14 END;

輸出結果如下:

1 第一個變量:22
2 第二個變量:王五

(2)通過%ROWTYPE 的聲明寫法
  %ROWTYPE 該類型是提取行記錄時常用的存儲數據的方式。這種聲明方式,可以直接引用表中的行作為變量類型,它同%TYPE 在優點上類似,避免因表中字段的數據類型改變,而導致PL/SQL 塊出錯的問題。
  下邊是%ROWTYPE 的用法例子,挺簡單的:

1 DECLARE
2 v_obj ly_ds%rowtype; --ROWTYPE不區分大小寫
3 BEGIN
4  --into賦值給v_obj,會按照定義的type順序賦值
5 select * into v_obj from ly_ds where id='2'; 
6 dbms_output.put_line('第一個變量:'||v_obj.ly_nl);
7 dbms_output.put_line('第二個變量:'||v_obj.ly_mc);
8 END;

 

1  DECLARE
2  v_obj ly_ds%rowtype; --ROWTYPE不區分大小寫
3  BEGIN
4   --into賦值給v_obj,會按照定義的type順序賦值
5  select * into v_obj from ly_ds where id='2'; 
6  dbms_output.put_line('第一個變量:'||v_obj.ly_nl);
7  dbms_output.put_line('第二個變量:'||v_obj.ly_mc);
8  END;

 

 

 

注意一個地方,就是上邊的into 前邊,只能為 * ,如果要寫為具體的列,那就要寫全。

2、索引表類型(關聯數組)
  該類型與數組相似,利用鍵值查找對應的數據,但是這里的鍵值同我們真正的數組下標不同,這種索引表的下標,還可以為字符串,真正的數組下標都是數字。索引表中的數據可以是上邊介紹過的標量類型,也可以是記錄類型。當在賦值的過程中,對已存在的索引表下標重復賦值,則會替換以前的數據,這個很好理解。

  以下是我學習的時候,記錄的這部分內容,都寫在了下邊:

 1 DECLARE
 2   /**
 3    *聲明一個存儲ly_ds整行數據的索引表,下標為數字,
 4    *即 binary_integer
 5    */
 6   type index_row_type is table of ly_ds%rowtype index by binary_integer;
 8 
 9   /**
10    *聲明一個存儲字符串數據的索引表,下標也為數字,
11    *即 pls_integer
12    */
13   type index_val_type is table of varchar2(10) index by pls_integer;
15 
16   /**
17    *聲明一個存儲字符串數據的索引表,下標為字符串,
18    *即 varchar(100)、varchar(10),必須給固定大小
19    */
20   type index_str_val_type is table of varchar2(100) index by varchar(10);
22    /**
23     *定義一個下標為數字,存ly_ds一行的變量
24     */
25   v_row    index_row_type; 
26   /**
27    *定義一個下標為數字,存字符串的變量
28    */
29   v_val    index_val_type; 
30   /**
31    *定義一個下標為字符串,存字符串的變量
32    */
33   v_str_val    index_str_val_type; 
34 BEGIN
35  /**
36   *為下標為數字的 字符串索引表下標1賦值
37   */
38   v_val(1) :='正數'; 
39   /**
40   *為下標為數字的 字符串索引表下標-1賦值
41   */
42   v_val(-1) :='負數'; 
43   dbms_output.put_line('v_val中下標1的值:'||v_val(1));
44   dbms_output.put_line('v_val中下標-1的值:'||v_val(-1));
45 
46   /**
47   *將改行數據賦值給行變量的下標1上
48   */
49   select * into v_row(1) from ly_ds where id='2'; 
50   dbms_output.put_line('v_row(1)中ly_mc的值:'||v_row(1).ly_mc);
51   dbms_output.put_line('v_row(1)中ly_nl的值:'||v_row(1).ly_nl);
52 
53    /**
54     *為下標為字符串的 字符串索引表的下標one賦值
55     */
56   v_str_val('one') :='java天下第一';  
57    /**
58     *為下標為字符串的 字符串索引表的下標test賦值
59     */
60   v_str_val('test') :='java天下無敵'; 
61    /**
62     *為下標為字符串的 字符串索引表的下標test1賦值
63     */
64   v_str_val('test1') :='java太可怕了'; 
65   dbms_output.put_line('v_str_val中下標one的值:'||v_str_val('one'));
66   dbms_output.put_line('v_str_val中下標test的值:'||v_str_val('test'));
67   dbms_output.put_line('v_str_val中第一個值的下標:'||v_str_val.first);
68   dbms_output.put_line('v_str_val中第一個下標對應的值:'||v_str_val(v_str_val.first));
69   dbms_output.put_line('v_str_val中最后一個下標:'||v_str_val.last);
70 END;

運行后會有下邊的結果:

1 v_val中下標1的值:正數
2 v_val中下標-1的值:負數
3 v_row(1)中ly_mc的值:王五
4 v_row(1)中ly_nl的值:22
5 v_str_val中下標one的值:java天下第一
6 v_str_val中下標test的值:java天下無敵
7 v_str_val中第一個值的下標:one
8 v_str_val中第一個下標對應的值:java天下第一
9 v_str_val中最后一個下標:test1

上邊有個特別注意的問題,就是,定義下標和存儲的值的時候,一定要給出大小,比如字符串,不能寫成varchar ,必須要寫成varchar(100) 這樣有固定大小的類型。
  上邊我用了三種,一種是pls_integer 、binary_integer ,一種是ly_ds%rowtype ,這兩種都有固定的大小,第一種是數字類型,它們有固定的大小,可以百度一下。如果定義了標量類型那種,必須要要給出大小,這個需要注意下。

3、varry變長數組
  varry 數組,是另一種存儲有序元素的集合。集合下標從1開始,比較適合較少的數據使用。具體如下:
  它有一個注意的地方,就是數組在定義一個變量時候,一定要初始化 ,並且,在使用前 一定要先確定容量 。對於,在初始化時,已賦值的,可以不用定義存儲的大小了。這點與java 中的數組是一樣的。

 1 DECLARE
 2   /**
 3    *聲明一個最多容納100個數的varry數組,注意,它的下標是從1開始的。
 4    *即 binary_integer
 5    */
 6   type array_type is varray(100) of varchar(100);
 7   /**
 8    *分別定義一個直接賦值的和兩個未賦值的數組。
 9    *注意:一定要初始化,但可以不賦值。對於沒有賦值的這種數組,在用之前
10    *也一定要先確定容量。
11    */
12   v_val_array array_type := array_type('one','two');
13   v_val_array2 array_type := array_type();
14   v_val_array3 array_type := array_type();
15 BEGIN
16    /**
17     *獲取第一個varry數組中的值
18     *varry的下標從1開始
19     */
20     dbms_output.put_line('v_val_array中下標1的值:'||v_val_array(1));
21     dbms_output.put_line('v_val_array中下標2的值:'||v_val_array(2));
22 
23 
24    /**
25     *獲取第二個varry數組中的值
26     *因為第二個varry沒有初始化長度,所以通過extend方法,
27     *為該數組加一個空位
28     */
29     v_val_array2.extend;
30     v_val_array2(1) :='aaa'; 
31     v_val_array2.extend;
32     v_val_array2(2) :='bbb'; 
33     v_val_array2.extend;
34     v_val_array2(3) :='ccc'; 
35     dbms_output.put_line('v_val_array2中下標1的值:'||v_val_array2(1));
36     dbms_output.put_line('v_val_array2中下標2的值:'||v_val_array2(2));
37     dbms_output.put_line('v_val_array2中下標3的值:'||v_val_array2(3));
38 
39      /**
40     *獲取第三個varry數組中的值
41     *因為第三個varry沒有初始化長度,所以通過extend方法
42     *初始化空位
43     */
44 
45   /**
46     *獲取第二個varry數組中的值
47     *因為第二個varry沒有初始化長度,所以通過extend方法,
48     *為該數組初始化長度
49     */
50     v_val_array3.extend(v_val_array2.count());
51     v_val_array3(1) :='ddd'; 
52     v_val_array3(2) :='eee'; 
53     v_val_array3(3) :='fff'; 
54     dbms_output.put_line('v_val_array3中下標1的值:'||v_val_array3(1));
55     dbms_output.put_line('v_val_array3中下標2的值:'||v_val_array3(2));
56     dbms_output.put_line('v_val_array3中下標3的值:'||v_val_array3(3));
57 END;

結果

1 v_val_array中下標1的值:one
2 v_val_array中下標2的值:two
3 v_val_array2中下標1的值:aaa
4 v_val_array2中下標2的值:bbb
5 v_val_array2中下標3的值:ccc
6 v_val_array3中下標1的值:ddd
7 v_val_array3中下標2的值:eee
8 v_val_array3中下標3的值:fff

上邊分別是三種情況,其中有extend ,可能新手會感到迷惑。
  因為v_val_array2和v_val_array3 開始的時候,只是定義了變量,所以,在使用前,需要給出大小,extent 的用法,即是對數組的長度加1個空位 的意思。
  如果想直接為v_val_array3給出固定大小,可以直接v_val_array3.extend(3) ,這樣就會給v_val_array3 一個默認的存儲大小為3 ,也可以通過已有數組的大小,即是上邊的v_val_array3.extend(v_val_array2.count())。

  雖然上邊都是PL/SQL 那邊的知識,但是它們在存儲過程 中,都是通用的。變量這地方,浪費了挺長的時間,但是基礎有利用后邊的學習,我覺得浪費了這兩天應該會對自己有用處的。

 

 

 

 

 

 


原文鏈接:https://blog.csdn.net/wohaqiyi/article/details/81697710


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM