注:
以下測試案例所用的表均來自與scott方案,使用前,請確保該用戶解鎖.
1、簡介
和大多數編程語言一樣,在編寫PL/SQL程序時,可以定義常量和變量,在pl/sql程序中包括有:
a、標量類型(Scalar)
b、復合類型(Composite)
c、參照類型(Refrence)
d、lob(large object)類型
下面來一一介紹
2、標量(Scalar)類型 只能存放單個值的變量
在編寫pl/sql語句時,如果需要用到變量,那么就需要在定義部分定義變量。pl/sql中定義變量個常量的語法如下:
identifier [constant] datatype [not null] [:=| default expr]
identifier:名稱
constant:指定常量,需要指定它的初始值,且其值是不能改變的
datatype:數據類型
not null:指定變量值不能為空
:=給變量或者常量指定初始值
defalut:用於指定初試值
expr:指定初始值的pl/sql表達式,可是文本值、其他變量或者函數
2.1、標量定義的案例
定義一個變長字符串
v_name varchar2(10);
定義一個小數 范圍 -9999.99~9999.99
v_sal number(6,2)
定義一個小數,並給定初始值6.6 注: :=是pl/sql的變量賦值號
v_num number(6.2):=6.6
定義一個日期類型的數據
v_date date;
定一個布爾變量,不能為空,初始值為false;
v_bool boolean not null defalut false;
注:pl/sql中使用標量並給其賦初值的方式不同於其他的編程語言,需要在等號前加":"
2.2、標量使用的案例
作用:變量是存放pl/sql塊中最普通的變量
輸入一個員工號,顯示雇員的姓名、工資、個人所得稅(稅率為0.03),代碼如下:
declare c_tax_rate number(3,2):=0.03; v_name varchar2(5); v_sal number(7,2); v_tax_sal number(7,2); begin select ename,sal into v_name,v_sal from emp where empno=&no; v_tax_sal:=v_sal * c_tax_rate; dbms_output.put_line('姓名是:'||v_name||'工資:'||v_sal||'交稅:'||v_tax_sal); end;
ok,輸出成功!
但是上面的代碼存在漏洞

我們給變量指定了定長,但是如果我們輸入的編號對應的ename的長度大於5,就像下面這樣:

我輸入了7654,這時對應的ename的長度大於5,所以程序包錯了

所以必須解決這個問題,當我們不知道變量長度的時候,讓其長度和對應的表字段匹配,從而使程序不抱錯,解決方案參考2.3
2.3、標量中使用%type
declare c_tax_rate number(3,2):=0.03; v_name emp.ename%type; v_sal emp.sal%type; v_tax_sal emp.sal%type; begin select ename,sal into v_name,v_sal from emp where empno=&no; v_tax_sal:=v_sal * c_tax_rate; dbms_output.put_line('姓名是:'||v_name||'工資:'||v_sal||'交稅:'||v_tax_sal); end;

ok,再次輸入7654,正常輸出。
3、復合變量(composite) 用於存放多個值的變量
3.1、復合類型-pl/sql記錄
類似高級語言中的結構體,需要注意的是,當引用pl/sql記錄中的成員時,必須要加記錄變量作為前綴(記錄變量.記錄成員),如果定義一個pl/sql記錄類型呢?代碼如下:
declare type emp_record_type is record( name emp.ename%type, salary emp.sal%type );
這樣就定義了一個名為emp_record_type的復雜變量類型,那么如何使用這個類型呢?代碼如下:
sp_record emp_record_type;
ok,這樣就定義了一個emp_record_type類型的變量,名為sp_record;
declare type emp_record_type is record( name emp.ename%type, salary emp.sal%type ); sp_record emp_record_type; begin select ename,sal into sp_record from emp where empno=7788; dbms_output.put_line('員工名:'|| sp_record.name||'工資:'||sp_record.salary); end;

ok,使用復合類型-pl/sql記錄成功的輸出了員工名和工資
3.2、復合類型-pl/sql表
這種類型相當於高級語言的數組,但需要注意的是高級語言中的數組下標不能為負數,而pl/sql可以是可以為負數,而且表元素的下標沒有限制。如何定義一個pl/sql表類型呢?代碼如下:
declare type sp_table_type is table of emp.ename%type index by binary_integer;
ok,上面的代碼定義了一個類型為emp.ename的pl/sql表類型,也可以理解為類型為emp.ename的數組,那么如何使用這個類型,代碼如下:
sp_table sp_table_type
ok,這樣就定義了一個emp_table_type類型的變量,名為sp_table;
declare type sp_table_type is table of emp.ename%type index by binary_integer; sp_table sp_table_type; begin select ename into sp_table(0) from emp where emp.empno=7788; dbms_output.put_line('姓名是:'||sp_table(0)); end;

ok,上面的代碼將empno為7788的員工姓名放入了sp_table中,並指定其下標為0,所以我們在下面輸出時,指定輸出sp_table(0),所以正常輸出,
下面是使用pl/sql表類型經常出錯的地方:
i、但是當我們指定存放的下標為-1,而輸出的下標為0時,代碼就會報錯,具體的代碼如下:
declare type sp_table_type is table of emp.ename%type index by binary_integer; sp_table sp_table_type; begin select ename into sp_table(-1) from emp where emp.empno=7788; dbms_output.put_line('姓名是:'||sp_table(0)); end;

所以當我們使用pl/sql表類型時,需要注意下標的對應
ii、當查詢返回的結果集是多個,但是又指定pl/sql表類型的下標,相當於pl/sql表類型只接受一個值,這個時候會報錯,具體代碼如下:
declare type sp_table_type is table of emp.ename%type index by binary_integer; sp_table sp_table_type; begin select ename into sp_table(-1) from emp; dbms_output.put_line('姓名是:'||sp_table(-1)); end;

select ename from emp,返回了多個結果,而into sp_table(-1)只接受一個值,所以報上面的錯誤了。

4、參照變量
參照變量是指用於存放數值指針的變量,通過使用參照變量,可以使應用程序共享相同對象,從而降低占用的空間。在編寫pl/sql程序時,可以使用游標變量(ref cursor)和對象類型變量
(ref obj_type)兩種參照變量類型。
4.1、參照變量-ref cursor游標變量
使用游標時,當定義游標時,不需要指定相應的select 語句,但是當使用游標時,就需要指定select語句,這樣一個游標就和一個selec語句結合了.下面是游標的案例
a、請使用pl/sql編寫一個塊,可以輸入部門號,顯示該部門下所有員工的姓名和工資,代碼如下:
首先定義一個游標類型:
type sp_emp_cursor is ref cursor;
接着定義一個sp_emp_cursor游標類型的游標變量
test_cursor sp_emp_cursor;
然后打開游標,將游標與結果集結合
open test_cursor for select ename,sal from emp where empno=&no;
ok,現在test_cursor指向了select ename,sal from emp where empno=&no 結果集
然后循環游標,取出我們想要的數據,然后賦值給定義好的標量,並輸出給標量,循環完畢(游標使用完畢),關閉游標,代碼如下:
declare type sp_emp_cursor is ref cursor;--定義一個游標類型 test_cursor sp_emp_cursor;--定義一個游標變量 v_ename emp.ename%type; v_sal emp.sal%type; begin --執行 --把test_cursor和一個select結合 open test_cursor for select ename,sal from emp where deptno=&no; --循環取出 loop fetch test_cursor into v_ename,v_sal; --判斷test_cursor是否循環到空數據,如果循環到空數據,那么就停止循環 exit when test_cursor%notfound; dbms_output.put_line('姓名:'||v_ename||'工資:'||v_sal); end loop; --使用完畢關閉游標 close test_cursor; end;
ok,完成a需求。
b、在a的基礎上,如果某個員工的工資低於200元,就增加100元。使用游標完成需求。
