1. 程式人生 > >Oracle PL/SQL語句基礎學習筆記(上)

Oracle PL/SQL語句基礎學習筆記(上)

PL/SQL是ORACLE對標準資料庫語言的擴充套件,ORACLE公司已經將PL/SQL整合到ORACLE 伺服器和其他工具中了,近幾年中更多的開發人員和DBA開始使用PL/SQL,本文將講述PL/SQL基礎語法,結構和元件、以及如何設計並執行一個PL/SQL程式。  

1、PL/SQL的優點

從版本6開始PL/SQL就被可靠的整合到ORACLE中了,一旦掌握PL/SQL的優點以及其獨有的資料管理的便利性,那麼你很難想象ORACLE缺了PL/SQL的情形。PL/SQL 不是一個獨立的產品,他是一個整合到ORACLE伺服器和ORACLE工具中的技術,可以把PL/SQL看作ORACLE伺服器內的一個引擎,sql語句執行者處理單個的sql語句,PL/SQL引擎處理PL/SQL程式塊。當PL/SQL程式塊在PL/SQL引擎處理時,ORACLE伺服器中的SQL語句執行器處理pl/sql程式塊中的SQL語句。
  
  這裡寫圖片描述

(1).PL/SQL的優點

  • PL/SQL是一種高效能的基於事務處理的語言,能執行在任何ORACLE環境中,支援所有資料處理命令。通過使用PL/SQL程式單元處理SQL的資料定義和資料控制元素
  • PL/SQL支援所有SQL資料型別和所有SQL函式,同時支援所有ORACLE物件型別
  • PL/SQL塊可以被命名和儲存在ORACLE伺服器中,同時也能被其他的PL/SQL程式或SQL命令呼叫,任何客戶/伺服器工具都能訪問PL/SQL程式,具有很好的可重用性。
  • 可以使用ORACLE資料工具管理儲存在伺服器中的PL/SQL程式的安全性。可以授權或撤銷資料庫其他使用者訪問PL/SQL程式的能力。
  • PL/SQL程式碼可以使用任何ASCII文字編輯器編寫,所以對任何ORACLE能夠執行的作業系統都是非常便利的
  • 對於SQL,ORACLE必須在同一時間處理每一條SQL語句,在網路環境下這就意味作每一個獨立的呼叫都必須被oracle伺服器處理,這就佔用大量的伺服器時間,同時導致網路擁擠。而PL/SQL是以整個語句塊發給伺服器,這就降低了網路擁擠

2、PL/SQL塊結構

PL/SQL是一種塊結構的語言,組成PL/SQL程式的單元是邏輯塊,一個PL/SQL 程式包含了一個或多個邏輯塊,每個塊都可以劃分為三個部分。與其他語言相同,變數在使用之前必須宣告,PL/SQL提供了獨立的專門用於處理異常的部分。

(1).PL/SQL塊語法

[DECLARE]
---declaration statements
BEGIN ---executable statements [EXCEPTION] ---exception statements END

(2).PL/SQL塊三部分:

  • 宣告部分(Declaration section)

宣告部分包含了變數和常量的資料型別和初始值。這個部分是由關鍵字DECLARE開始,如果不需要宣告變數或常量,那麼可以忽略這一部分;需要說明的是遊標的宣告也在這一部分。

  • 執行部分(Executable section)

執行部分是PL/SQL塊中的指令部分,由關鍵字BEGIN開始,所有的可執行語句都放在這一部分,其他的PL/SQL塊也可以放在這一部分。

  • 異常處理部分(Exception section)

這一部分是可選的,在這一部分中處理異常或錯誤,對異常處理的詳細討論我們在後面進行。

PL/SQL塊中的每一條語句都必須以分號結束,SQL語句可以使多行的,但分號表示該語句的結束。一行中可以有多條SQL語句,他們之間以分號分隔。每一個PL/SQL塊由BEGIN或DECLARE開始,以END結束。註釋由–標示。

(3).PL/SQL塊的命名和匿名

PL/SQL程式塊可以是一個命名的程式塊也可以是一個匿名程式塊。匿名程式塊可以用在伺服器端也可以用在客戶端。

命名程式塊可以出現在其他PL/SQL程式塊的宣告部分,這方面比較明顯的是子程式,子程式可以在執行部分引用,也可以在異常處理部分引用。

(4).可儲存程式

PL/SQL程式塊可背獨立編譯並存儲在資料庫中,任何與資料庫相連線的應用程式都可以訪問這些儲存的PL/SQL程式塊。

ORACLE提供了四種類型的可儲存的程式:

  • 函式
  • 過程
  • 觸發器

函式
函式是命名了的、儲存在資料庫中的PL/SQL程式塊。函式接受零個或多個輸入引數,有一個返回值,返回值的資料型別在建立函式時定義。
定義函式的語法如下:

FUNCTION name [{parameter[,parameter,...])] RETURN datatypes IS
[local declarations]
BEGIN
execute statements
[EXCEPTION
exception handlers]
END [name]

過程

儲存過程是一個PL/SQL程式塊,接受零個或多個引數作為輸入(INPUT)或輸出(OUTPUT)、或既作輸入又作輸出(INOUT),與函式不同,儲存過程沒有返回值,儲存過程不能由SQL語句直接使用,只能通過EXECUT命令或PL/SQL程式塊內部呼叫。

語法:

PROCEDURE name [(parameter[,parameter,...])] IS
[local declarations]
BEGIN
execute statements
[EXCEPTION
exception handlers ]
END [name] 

包(package)

包其實就是被組合在一起的相關物件的集合,當包中任何函式或儲存過程被呼叫,包就被載入入記憶體中,包中的任何函式或儲存過程的子程式訪問速度將大大加快。
包由兩個部分組成:規範和包主體(body),規範描述變數、常量、遊標、和子程式,包體完全定義子程式和遊標。

觸發器(trigger)

觸發器與一個表或資料庫事件聯絡在一起的,當一個觸發器事件發生時,定義在表上的觸發器被觸發。

3、宣告部分

(1).宣告變數

變數存放在記憶體中以獲得值,能被PL/SQL塊引用。你可以把變數想象成一個可儲藏東西的容器,容器內的東西是可以改變的。

變數一般都在PL/SQL塊的宣告部分宣告,PL/SQL是一種強壯的型別語言,這就是說在引用變數前必須首先宣告,要在執行或異常處理部分使用變數,那麼變數必須首先在宣告部分進行宣告。

語法:

Variable_name [CONSTANT] databyte [NOT NULL][:=|DEFAULT expression] 

注意:可以在宣告變數的同時給變數強制性的加上NOT NULL約束條件,此時變數在初始化時必須賦值。

給變數賦值有兩種方式:

  • 直接給變數賦值
X:=200;
Y=Y+(X*20);
  • 通過SQL SELECT INTO 或FETCH INTO給變數賦值
SELECT SUM(SALARY),SUM(SALARY*0.1)
INTO TOTAL_SALARY,TATAL_COMMISSION
FROM EMPLOYEE
WHERE DEPT=10;

(2).宣告%TYPE和%ROWTYPE型別的變數

在定義變數時處理可以使用oracle規定的資料型別外,還可以使用%TYPE和%ROWTYPE來定義變數。

%TYPE型別的變數是專門為儲存在資料列中檢索到的值而建立的.對於使用%TYPE建立的變數,其資料型別由系統根據檢索的資料列的資料型別決定.

%ROWTYPE型別的變數,它可以一次儲存從資料庫檢索的一行資料。

當你不知道表中的資料型別是什麼時候?那你就考慮%TYPE來解決此問題。

SQL> declare  
      empno emp.empno%TYPE; //宣告的時候一定要加上表的中列  
      ename emp.ename%TYPE;  
      job   emp.job%TYPE;  
     begin  
      select empno,ename,job into empno,ename,job from emp   where empno='7369';  
      dbms_output.put_line(empno||'/'||ename||'/'||job);  
     end;  
     /   
7369/SMITH/CLERK

emp.empno%TYPE;解析:首先它到emp表中去查詢empno列 %TYPE返回其資料的資料型別。

%TYPE的好處:

  • 可移植性高(當我們對錶的資料型別發生改變時,使用者不必考慮定義變數型別)
  • 使用者不必檢視資料型別就可以定義變數能夠儲存檢索的資料。

%ROWTYPE

SQL> declare  
      row_data emp%ROWTYPE;  
     begin  
      select * into row_data from emp where empno='7369';      dbms_output.put_line(row_data.empno||'/'||row_data.ename||'/'||row_data.job);  
     end;  
     /  

注意:如果定義了%rowtype型別的變數,該變數的結構與定義表的結構完全相同,查詢時必須使用*或者列舉全部的欄位資訊。

(3).複合變數

複合變數可以將不同的資料型別的多個值儲存在一個單元中.由於複合資料型別可以有使用者根據需要定義其結構,所以複合資料型別也稱為自定義資料型別。

PL/SQL提供了兩種型別的複合資料型別:

  • 記錄型別
  • 記錄表型別

記錄型別

在記錄型別中可以儲存多個標量值,與資料庫中的行相似,必須使用TYPE語句定義記錄型別。

語法:

TYPE record_name is record(  
Field_name data_type[not null, :=default value]  
………  
);  

案例:

SQL> declare  
     type empinfo is record( //宣告一個記錄型別  
       empno number(4),  
       ename varchar2(10),  
       job varchar2(9)  
      );  

     emp_data empinfo; //宣告一個記錄型別的變數  
     begin  
     select empno,ename,job into emp_data from emp where empno=7369; //查詢的結果賦值給定義的變數  
     dbms_output.put_line(emp_data.empno||'/'||emp_data.ename||'/'||emp_data.job);  
     end;  
     /  

與%Rowtype不同之處是

  • %rowtype查詢的是全部資料
  • 記錄型別必須使用type語法格式宣告

記錄表型別

允許使用者在程式程式碼中使用”表”,以便儲存多個行的資料。它只在程式執行期間有效。類似於程式程式碼中集合|陣列。 它可以處理多個記錄或多個行記錄。為什麼使用記錄表型別呢?因為我們查詢的資料的往往需要返回多行記錄,所以需要記錄表型別。

語法:

TYPE table_name is table of data_type[not null]  
     Index by binary_integer;//主鍵的索引  
declare  
   type table_emp is table of emp%rowtype //建立一個表 此表的型別與emp表的型別一致  
   index by binary_integer;  

   type table_text is table of varchar2(20) //建立一個表 此表具有一個varchar2列的簡單表  
   index by binary_integer;  

   empt table_emp; //宣告記錄表型別的變數  
   tabtext table_text;  
begin  

案例:

SQL> declare  
      type table_emp is table of emp%rowtype  
      index by binary_integer;  
      empt table_emp;  
     begin  
      empt(1).ename:='wangyi';  
      dbms_output.put_line(empt(1).ename);  
     end;  
     /  
//返回總記錄  
SQL> declare  
      type table_emp is table of emp%rowtype  
      index by binary_integer;  
      empt table_emp;  
     begin  
      dbms_output.put_line(empt.count);  
     end;  
     /
0 //沒有記錄  

//刪除的操作
表名.Delete(記錄數);

//檢索記錄變數
First:獲取第一個的索引
Next:下一個的索引 但是必須有引數
Last:最後一個的索引

SQL> declare  
      type table_emp is table of emp%rowtype  
      index by binary_integer;  
      empt table_emp;  
      i number(2):=1;  
     begin  
       while i<10  
       loop  
         empt(i).ename:='wangyi';  
         i:=i+1;  
       end loop;
      dbms_output.put_line(empt.count);
      empt.delete(2); 
      dbms_output.put_line(empt.count);
      dbms_output.put_line(empt.first);  
      dbms_output.put_line(empt.next(2));  
      dbms_output.put_line(empt.last);  
     end;  
     /
9  
8  
1  
3  
9

//查詢資料庫的資料賦值給你建立的記錄表型別

SQL> declare  
      type table_emp is table of emp%rowtype  
      index by binary_integer;  
      empt table_emp;  
      i number(10):=0;  
     begin
      for rec in (select * from emp) loop  
        i:=i+1;  
        empt(i).ename:=rec.ename;  
       end loop;  

      dbms_output.put_line(empt.count);  
     end;  
     /
15  
//把查詢的的資料全部賦值給記錄表型別  
declare  
   type table_emp is table of emp%rowtype  
   index by binary_integer;  
   empt table_emp;  
   i number(10):=0;  
   j number(10):=1;  
begin
   for rec in (select * from emp) loop  
     i:=i+1;  
     empt(i).empno:=rec.empno;  
     empt(i).ename:=rec.ename;  
     empt(i).job:=rec.job;  
     empt(i).mgr:=rec.mgr;  
     empt(i).hiredate:=rec.hiredate;  
     empt(i).sal:=rec.sal;  
     empt(i).comm:=rec.comm;  
     empt(i).deptno:=rec.deptno;  
    end loop;
    while j<=empt.count loop  dbms_output.put_line(empt(j).empno||'/'||empt(j).ename||'/'||empt  
(j).job||'/'||empt(j).mgr||'/'||empt(j).hiredate||'/'||empt(j).sal||'/'||empt  
(j).comm||'/'||empt(j).deptno);  
   j:=j+1;  
 end loop;  
end;  
/ 

SQL> declare  
      type table_emp is table of emp%rowtype  
      index by binary_integer;  
      empt table_emp;  
      i number(10):=0;  
      j number(10):=1;  
     begin
      for rec in (select * from emp) loop  
        i:=i+1;  
        empt(i).empno:=rec.empno;  
        empt(i).ename:=rec.ename;  
        empt(i).job:=rec.job;  
        empt(i).mgr:=rec.mgr;  
        empt(i).hiredate:=rec.hiredate;  
        empt(i).sal:=rec.sal;  
        empt(i).comm:=rec.comm;  
        empt(i).deptno:=rec.deptno;  
      end loop;
      dbms_output.put_line(empt.count);
      while j<=empt.count loop  
      dbms_output.put_line(empt(j).empno||'/'||empt(j).ename||'/'||empt (j).job||'/'||empt(j).mgr||'/'||empt(j).hiredate||'/'||empt(j).sal||'/'||empt  
  (j).comm||'/'||empt(j).deptno);  
      j:=j+1;  
     end loop;  
  end;  
  /

(4).常量

常量與變數相似,但常量的值在程式內部不能改變,常量的值在定義時賦予,,他的宣告方式與變數相似,但必須包括關鍵字CONSTANT。常量和變數都可被定義為SQL和使用者定義的資料型別。

ZERO_value CONSTANT NUMBER:=0; 

這個語句定了一個名叫ZERO_value、資料型別是NUMBER、值為0的常量。

(5).標量(scalar)資料型別

標量(scalar)資料型別沒有內部元件,他們大致可分為以下四類:

  • number
  • character
  • date/time
  • boolean

表1顯示了數字資料型別;表2顯示了字元資料型別;表3顯示了日期和布林資料型別。

Scalar Types:Numeric

Datatype        Range              Subtypes description 
BINARY_INTEGER  -214748-2147483647 NATURAL
NATURAL
NPOSITIVE
POSITIVEN
SIGNTYPE 

用於儲存單位元組整數。
要求儲存長度低於NUMBER值。
用於限制範圍的子型別(SUBTYPE):
NATURAL:用於非負數
POSITIVE:只用於正數
NATURALN:只用於非負數和非NULL值
POSITIVEN:只用於正數,不能用於NULL值
SIGNTYPE:只有值:-1、0或1.
NUMBER 1.0E-130-9.99E125 DEC
DECIMAL
DOUBLE
PRECISION
FLOAT
INTEGERIC
INT
NUMERIC
REAL
SMALLINT 儲存數字值,包括整數和浮點數。可以選擇精度和刻度方式,

語法:

number[([,])]

預設的精度是38,scale是0.
PLS_INTEGER -2147483647-2147483647 與BINARY_INTEGER基本相同,但採用機器運算時,PLS_INTEGER提供更好的效能 。

字元資料型別

datatype rang                 subtype     description 
CHAR     最大長度32767位元組      CHARACTER    儲存定長字串,如果長度沒有確定,預設是1 
LONG     最大長度2147483647位元組              儲存可變長度字串 
RAW      最大長度32767位元組                 用於儲存二進位制資料和位元組                                                         字串,當在兩個資料庫之間進行傳遞時,RAW資料不在字符集之間進行轉換。 


LONGRAW  最大長度2147483647LONG資料型別相似,同樣他也不能在字符集之間進行轉換。 
ROWID    18個位元組                           與資料庫ROWID偽列型別相 同,能夠儲存一個行標示符,可以將行標示符看作資料庫中每一行的唯一鍵值。 
VARCHAR2 最大長度32767位元組     STRINGVARCHAR 與VARCHAR資料型別相似,儲存可變長度的字串。宣告方法與VARCHAR相同  

DATE和BOOLEAN

datatype range          description 
BOOLEAN  TRUE/FALSE     儲存邏輯值TRUEFALSE,無引數 
DATE     01/01/4712 BC  儲存固定長的日期和時間值,日期值中包含時間 

(6).LOB資料型別

LOB(大物件,Large object) 資料型別用於儲存類似影象,聲音這樣的大型資料物件,LOB資料物件可以是二進位制資料也可以是字元資料,其最大長度不超過4G。LOB資料型別支援任意訪問方式,LONG只支援順序訪問方式。LOB儲存在一個單獨的位置上,同時一個”LOB定位符”(LOB locator)儲存在原始的表中,該定位符是一個指向實際資料的指標。

在PL/SQL中操作LOB資料物件使用ORACLE提供的包DBMS_LOB.LOB資料型別可分為以下四類:

  • BFILE
  • BLOB
  • CLOB
  • NCLOB

(7).操作符

與其他程式設計語言相同,PL/SQL有一系列操作符。操作符分為下面幾類:

  • 算術操作符
  • 關係操作符
  • 比較操作符
  • 邏輯操作符

算術操作符

operator operation 
+        -        減 
/        除 
*        乘 
**       乘方 

關係操作符主要用於條件判斷語句或用於where子串中,關係操作符檢查條件和結果是否為true或false。

關係操作符

operator operation 
<        小於操作符 
<=       小於或等於操作符 
>        大於操作符 
>=       大於或等於操作符 
=        等於操作符  
!=       不等於操作符 
<>       不等於操作符 
:=       賦值操作符 

比較操作符

operator  operation 
IS NULL   如果運算元為NULL返回TRUE 
LIKE      比較字串值 
BETWEEN   驗證值是否在範圍之內 
IN        驗證運算元在設定的一系列值中

邏輯操作符

operator operation 
AND      兩個條件都必須滿足 
OR       只要滿足兩個條件中的一個 
NOT      取反 

4、執行部分

執行部分包含了所有的語句和表示式,執行部分以關鍵字BEGIN開始,以關鍵字EXCEPTION結束,如果EXCEPTION不存在,那麼將以關鍵字END結束。分號分隔每一條語句,使用賦值操作符:=或SELECT INTO或FETCH INTO給每個變數賦值,執行部分的錯誤將在異常處理部分解決,在執行部分中可以使用另一個PL/SQL程式塊,這種程式塊被稱為巢狀塊所有的SQL資料操作語句都可以用於執行部分,PL/SQL塊不能再螢幕上顯示SELECT語句的輸出。SELECT語句必須包括一個INTO子串或者是遊標的一部分,執行部分使用的變數和常量必須首先在宣告部分宣告,執行部分必須至少包括一條可執行語句,NULL是一條合法的可執行語句,事物控制語句COMMIT和ROLLBACK可以在執行部分使用,資料定義語言(Data Definition language)不能在執行部分中使用,DDL語句與EXECUTE IMMEDIATE一起使用或者是DBMS_SQL呼叫。(??)

執行一個PL/SQL塊

SQL*PLUS中匿名的PL/SQL塊的執行是在PL/SQL塊後輸入“/”來執行,如下面的例子所示:

declare 
 v_comm_percent constant number:=10;
begin
 update emp
 set comm=sal*v_comm_percent
 where deptno=10;
 end
SQL> /
PL/SQL procedure successfully completed.
SQL> 

命名的程式與匿名程式的執行不同,執行命名的程式塊必須使用execute關鍵字:

create or replace procedure update_commission
 (v_dept in number,v_pervent in number default 10) is 
begin
 update emp
 set comm=sal*v_percent
 where deptno=v_dept;
end
SQL>/
Procedure created
SQL>execute update_commission(10,15);
PL/SQL procedure successfully completed.
SQL>  

如果在另一個命名程式塊或匿名程式塊中執行這個程式,那麼就不需要EXECUTE關鍵字。

declare
 v_dept number;
begin
 select a.deptno
 into v_dept
 from emp a
 where job='PRESIDENT'
 update_commission(v_dept);
end
SQL>/
 PL/SQL procedure successfully completed
SQL> 

5、控制結構

控制結構控制PL/SQL程式流程的程式碼行,PL/SQL支援條件控制和迴圈控制結構。

(1).條件控制

IF..THEN

語法:

IF condition THEN
 Statements 1;
 Statements 2;
 ....
END IF 

IF語句判斷條件condition是否為TRUE,如果是,則執行THEN後面的語句,如果condition為false或NULL則跳過THEN到END IF之間的語句,執行END IF後面的語句。

IF..THEN…ELSE

語法:

IF condition THEN
 Statements 1;
 Statements 2;
 ....
ELSE
 Statements 1;
 Statements 2;
 ....
END IF

如果條件condition為TRUE,則執行THEN到ELSE之間的語句,否則執行ELSE到END IF之間的語句。

IF 可以巢狀,可以在IF 或IF ..ELSE語句中使用IF或IF..ELSE語句。

if (a>b) and (a>c) then
  g:=a;
else
  g:=b;
  if c>g then
   g:=c;
  end if
end if 

IF..THEN..ELSIF

語法:

IF condition1 THEN
 statement1;
ELSIF condition2 THEN
 statement2;
ELSIF condition3 THEN
 statement3;
ELSE
 statement4;
END IF;
 statement5;

如果條件condition1為TRUE則執行statement1,然後執行statement5,否則判斷condition2是否為TRUE,若為TRUE則執行statement2,然後執行statement5,對於condition3也是相同的,如果condition1,condition2,condition3都不成立,那麼將執行statement4,然後執行statement5。

  
(2).迴圈控制

迴圈控制的基本形式是LOOP語句,LOOP和END LOOP之間的語句將無限次的執行。

LOOP..END LOOP

LOOP 
    statements;
END LOOP

LOOP和END LOOP之間的語句無限次的執行顯然是不行的,那麼在使用LOOP語句時必須使用EXIT語句,強制迴圈結束,例如:

X:=100;
LOOP
 X:=X+10;
 IF X>1000 THEN
  EXIT;
 END IF
END LOOP;
Y:=X; 

此時Y的值是1010。

LOOP..EXIT WHEN..END LOOP

EXIT WHEN語句將結束迴圈,如果條件為TRUE,則結束迴圈。

X:=100;
LOOP
X:=X+10;
EXIT WHEN X>1000;
X:=X+10;
END LOOP;
Y:=X;

WHILE..LOOP..END LOOP

WHILE..LOOP有一個條件與迴圈相聯絡,如果條件為TRUE,則執行迴圈體內的語句,如果結果為FALSE,則結束迴圈。

X:=100;
WHILE X<=1000 LOOP
 X:=X+10;
END LOOP;
Y=X;  

FOR…LOOP

語法:

FOR counter IN [REVERSE] start_range....end_range LOOP
statements;
END LOOP; 

LOOP和WHILE迴圈的迴圈次數都是不確定的,FOR迴圈的迴圈次數是固定的,counter是一個隱式宣告的變數,他的初始值是start_range,第二個值是start_range+1,直到end_range,如果start_range等於end _range,那麼迴圈將執行一次。如果使用了REVERSE關鍵字,那麼範圍將是一個降序。

X:=100;
FOR v_counter in 1..10 loop
x:=x+10;
end loop
y:=x; 

如果要退出for迴圈可以使用EXIT語句。

6、標籤

使用者可以使用標籤使程式獲得更好的可讀性。程式塊或迴圈都可以被標記。標籤的形式是<>。

標記程式塊

<>
[DECLARE]
... ... ...
BEGIN
........
[EXCEPTION]
.......
END label_name 
  標記迴圈
<>
LOOP
.........
<>
loop
..........
<>
loop
....
EXIT outer_loop WHEN v_condition=0;
end loop innermost_loop;
..........
END LOOP inner_loop;
END LOOP outer_loop;

7、GOTO語句

語法:
  

GOTO LABEL;

執行GOTO語句時,控制會立即轉到由標籤標記的語句。PL/SQL中對GOTO語句有一些限制,對於塊、迴圈、IF語句而言,從外層跳轉到內層是非法的。

X :=100;
FOR V_COUNTER IN 1..10 LOOP
 IF V_COUNTER =4 THEN
  GOTO end_of_loop
 END IF
 X:=X+10;
 <>
 NULL
END LOOP
Y:=X;  

注意:NULL是一個合法的可執行語句。

8、巢狀

程式塊的內部可以有另一個程式塊這種情況稱為巢狀。巢狀要注意的是變數,定義在最外部程式塊中的變數可以在所有子塊中使用,如果在子塊中定義了與外部程式塊變數相同的變數名,在執行子塊時將使用子塊中定義的變數。子塊中定義的變數不能被父塊引用。同樣GOTO語句不能由父塊跳轉道子塊中,反之則是合法的。

《OUTER BLOCK》
DECLARE
 A_NUMBER INTEGER;
 B_NUMBER INTEGER;
BEGIN
 --A_NUMBER and B_NUMBER are available here
 <>
 DECLARE
 C_NUMBER INTEGER
 B_NUMBER NUMBER(20)
BEGIN
 C_NUMBER:=A_NUMBER;
 C_NUMBER=OUTER_BLOCK.B_NUMBER;
END SUB_BLOCK;
END OUT_BLOCK;