PL/SQL變量和類型


  變量

  在定義變量時一定要為其指定一個類型,類型可以是PL/SQL類型或SQL語言的類型,一旦變量的類型確定,那么變量中所能存儲的值也就確定了,因此盡管變量的值會經常改變,但是值的類型是不可以變化的。

1.變量的聲明

  語法:variable_name[CONSTANT] type [NOT NULL] [:=value];

  variable_name:用於定義變量名,變量名的命名要符合標識符命名規范。

  type:變量需要使用的數據類型,可以使用所有SQL類型或PL/SQL類型。

用方括號 [] 括起來的是可選部分。

  CONSTANT:表示聲明為一個常量,常量在定義時需要指定初始值,一旦定義其值,不能再被改變。

  NOT NULL:用於約束變量的值不能為空。

  :=value :用於為變量賦初始值。

代碼1.1 變量定義示例

DECLARE

  v_empname VARCHAR2(20);     --定義員工名稱變量

  v_deptname VARCHAR2(20);    --定義部門名稱變量

  v_hiredate DATE NOT NULL := SYSDATE;  --定義入職日期變量

  v_empno INT NOT NULL DEFAULT 1111;  --變量員工編碼變量

BEGIN

  NULL;   --不執行任何代碼

END;

/

注:   :=和DEFAULT是可以互換使用的,都用來為變量賦初始值。

    一旦出現了NOT NULL關鍵字,后面必須具有賦初始值的語句。

 

2.變量的賦值

  如果變量在聲明時沒有指定初始值,默認情況下,變量被初始化為NULL值。如果未給變量賦值,就直接使用變量,將會產生意想不到的結果。

  根據變量的不同類型,可以為變量直接賦常量值,也可以使用表達式來計算變量的值。

  下面的代碼根據薪資和加薪比例來計算員工的結果薪資值:

DECLARE

  v_salary NUMBER(7,2);

  v_rate NUMBER(7,2) :=0.12;

  v_base_salary NUMBER(7,2) :=1200;

BEGIN

   v_salary := v_base_salary*(1+v_rate); --使用表達式為變量賦值

  DBMS_OUTPUT.put_line('員工的薪資值為:'||v_salary);

END;

 

在為PL/SQL變量賦值時,需要注意變量的類型。下面列出了常用的變量類型的復制方式。

DECLARE

  v_string VARCHAR2(200);

  v_hire_date DATE;

  v_bool BOOLEAN;  --PL/SQL布爾類型

BEGIN

  v_bool:=True;  --為布爾類型賦值

  v_hire_date:=to_date('2019-04-28','yyyy-mm-dd'); --使用函數為日期賦值

  v_hire_date:=SYSDATE;  --使用日期函數賦值

  v_hire_date:=date'2019-04-28';  --直接賦靜態日期值

  v_string:='this is a string';

END;

/

 

通過數據庫查詢為變量賦數據庫中的值,這是進行PL/SQL編程非常常見的賦值方式,例如要從emp表中查詢員工的姓名、員工編號和雇佣日期,可以使用如下PL/SQL代碼。

DECLARE

  v_empno  emp.empno%TYPE;  --定義變量

  v_ename  emp.ename%TYPE;

  v_hiredate  emp.hiredate%TYPE;

BEGIN

  SELECT empno , ename , hiredate 

  INTO v_empno , v_ename , v_hiredate

  FROM emp

  WHERE empno = &empno;

  --輸出變量的內容

  DBMS_OUTPUT.put_line('員工編號:' || v_empno);

  DBMS_OUTPUT.put_line('員工名稱:' || v_ename);

  DBMS_OUTPUT.put_line('雇佣日期:' || v_hiredate);

END;

  在定義變量類型時,使用了%TYPE來聲明與數據庫列相同的類型,然后通過SELECT-INTO語句查詢數據庫並將結果寫入變量中,可以看到INTO子句中的變量的順序要與列的順序一致。

  如果SELECT-INTO查詢返回多行數據會觸發TOO_MANY_ROWS異常,如果未找到任何行數據,會觸發NO_DATA_FOUND異常。

3.使用%TYPE

  使用PL/SQL的%TYPE,使得開發人員可以給予已有的變量類型,或者是數據列的類型來指定變量的類型。

DECLARE

  v_empno  emp.empno%TYPE;  --使用%TYPE定義emp表empno列類型的變量

  v_empno2  v_empno%TYPE;  --定義與v_empno相同的變量

  v_salary NUMBER(7,3) NOT NULL:=1350.5;  --定義薪水變量

  v_othersalary  v_salary%TYPE:=1500;  --定義與v_salary相同類型的變量

BEGIN

  NULL;

END;

/

  代碼中的v_empno使用%TYPE定義了與emp表中empno列相同的類型,而v_empno2定義了與v_empno相同的類型,因此

當emp表中的empno列的類型發生改變后,變量的類型會自動發生變化,並不需要手動地進行維護。

  v_salary是一個具有NOT NULL約束的變量聲明,在聲明時為這個變量指定了初始值,

v_othersalary使用%TYPE定義了與v_salary相同的類型,因此也具有NOT NULL約束。

在聲明時同樣為v_othersalary指定了變量的初始值,如果不指定這個初始值,PL/SQL引擎會觸發異常。

 

注意:盡管v_othersalary會因為NOT NULL而觸發異常,但是emp表的empno列是不允許為空的,對於數據庫列類型,%TYPE只提供類型信息,並不提供NOT NULL約束信息,因此即便沒有為v_empno或v_empno2指定初始值,也能夠正常運行。

  通過%TYPE的類型映射功能,使得在類型發生改變時非常容易對代碼進行維護,這是一種非常好的編碼風格,特別是在操作數據庫時,使用%TYPE會使得PL/SQL更加靈活。

4.使用%ROWTYPE

%ROWTYPE是與%TYPE相似的用於綁定到數據庫表列的類型,%TYPE僅綁定到單個數據庫列的類型,而%ROWTYPE則綁定到一整行的所有列類型,可以將使用%ROWTYPE定義的變量看作是一條數據類型,使用%ROWTYPE的示例代碼如下:

DECLARE

  v_emp   emp%ROWTYPE  --定義emp表的所有列類型

BEGIN           --查詢emo表並將結果寫入v_emp記錄中

  SELECT *

  INTO v_emp

  FROM emp

  WHERE empno = &empno;

  --輸出結果信息

DBMS_OUTPUT.put_line(v_emp.empno || CHR(10) || v_emo.ename);

END;

  代碼使用SELECT-INFO直接將一整列的數據插入使用%ROWTYPE定義的記錄類型,然后使用DBMS_OUTPUT.put_line輸出了最終的結果。

在PL/SQL中,CHR(13)表示回車,CHR(10)表示換行,通常使用CHR(13)||CHR(10)來進行回車換行。

 

使用%ROWTYPE定義了整行的記錄類型后,可以直接使用賦值語法為變量賦值,然后直接使用記錄類型字段值插入數據庫表。

DECLARE

  v_emp  emp%ROWTYPE;  --定義emp表列類型的記錄

BEGIN           --為記錄類型賦值

  v_emp.empno:=8000;

  v_emp.ename:='張三豐';

  v_emp.job:='掌門';

  v_empmgr:=7902;

  v_emp.hiredate:=date'2019-04-28';

  v_emp.sal:=8000;

  v_emp.deptno:=20;

  INSERT INTO emp VALUES v_emo;  --將記錄類型插入數據表

END;

/

  上面的代碼在使用%ROWTYPE定義了變量之后使用賦值語法為記錄中的每個列進行了賦值,最后使用INSERT INTO 語句直接將記錄類型插入emp數據表中。

注意:%ROWTYPE與%TYPE一樣,只提供類型信息,並不能保證NOT NULL約束。

 

除了使用%ROWTYPE定義表列類型的變量外,還可以用來定義游標類型的變量,使用%ROWTYPE指定游標類型的變量,變量的值將是游標的SELECT語句查詢出來的值,。

下面代碼定義了游標emp_cursor,使用%ROWTYPE指定emp_cursor類型的變量。

DECLARE

  CURSOR emp_cursor               --定義游標類型

  IS

    SELECT empno , ename , job , sal , hiredate

  FROM emp;

  --使用%ROWTYPE定義了游標類型的變量

  v_emp  emp_cursor%ROWTYPE;

BEGIN 

  OPEN emp_cursor;

  --循環並提取游標數據

  LOOP

    FETCH emp_cursor

      INTO v_emp;

  --要注意游標移動到最尾部退出游標

  EXIT WHEN emp_cursor%NOTFOUND;

  --輸出游標數據

  DBMS_OUTPUT.put_line(  v_emp.empno

                ||''

               ||v_emp.ename

                ||''

               ||v_emp.job

                ||''

               ||v_emp.sal

                ||''

               ||TO_CHAR(v_emp.hiredate,'YYYY-MM-DD')

            );

  END LOOP;

    --關閉游標

  CLOSE emp_cursor;

END;

/

代碼定義了游標emo_cursor,然后定義了該游標類型的v_emp變量,使用%ROWTYPE指定類型為游標返回類型,通過提取游標的FETCH-INTO語句,一次將一行數據寫入v_emp變量中,然后使用DBMS_OUTPUT.put_line來輸出結果值。

 

 

參考Oracle PL/SQL從入門到精通 清華大學出版社 作者:丁士鋒


免責聲明!

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



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