第二章 PL/SQL 塊結(jié)構(gòu)和組成元素

PL/SQL 塊

PL/SQL 程序由三個塊組成,即聲明部分厢岂、執(zhí)行部分、異常處理部分

  • PL/SQL 塊的結(jié)構(gòu)如下:
DECLARE   
/* 聲明部分 : 在此聲明 PL/SQL用到的變量 , 類型及游標(biāo),以及局部的存儲過程和函數(shù) */ 
BEGIN     
/*  執(zhí)行部分 :  過程及 SQL 語句  , 即程序的主要部分  */ 
EXCEPTION    
/* 執(zhí)行異常部分 : 錯誤處理  */ 
END; 

其中執(zhí)行部分是必須的缤骨。

  • PL/SQL 塊可以分為三類:
  • 無名塊:動態(tài)構(gòu)造浮禾,只能執(zhí)行一次交胚。
  • 子程序:存儲在數(shù)據(jù)庫中的存儲過程、函數(shù)及包等盈电。當(dāng)在數(shù)據(jù)庫上建立好后可以在其它程序中調(diào)用它們蝴簇。
  • 觸發(fā)器:當(dāng)數(shù)據(jù)庫發(fā)生操作時,會觸發(fā)一些事件匆帚,從而自動執(zhí)行相應(yīng)的程序熬词。
PL/SQL 結(jié)構(gòu)
  • PL/SQL 塊中可以包含子塊;
  • 子塊可以位于 PL/SQL 中的任何部分吸重;
  • 子塊也即 PL/SQL 中的一條命令互拾;
標(biāo)識符

PL/SQL 程序設(shè)計中的標(biāo)識符定義與 SQL 的標(biāo)識符定義的要求相同。
要求和限制有:

  • 標(biāo)識符名不能超過 30 字符晤锹;
  • 第一個字符必須為字母摩幔;
  • 不分大小寫;
  • 不能用’-‘(減號);
  • 不能是 SQL 保留字鞭铆。 提示 : 一般不要把變量名聲明與表中字段名完全一樣 , 如果這樣可能得到不正確的結(jié)果 .

例如:下面的例子將會刪除所有的紀(jì)錄或衡,而不是 KING 的記錄;

DECLARE    
 Ename varchar2(20) := ’KING’; 
BEGIN  
 DELETE FROM emp WHERE ename=ename; 
END; 

變量命名在 PL/SQL 中有特別的講究车遂,建議在系統(tǒng)的設(shè)計階段就要求所有編程人員共同遵守一定的要求封断, 使得整個系統(tǒng)的文檔在規(guī)范上達(dá)到要求。下面是建議的命名方法:

標(biāo)識符 命名規(guī)則 例子
程序變量 V_name V_name
程序常量 C_Name C_company_name
游標(biāo)變量 Name_cursor Emp_cursor
異常標(biāo)識 E_name E_too_many
表類型 Name_table_type Emp_record_type
Name_table Emp
記錄類型 Name_record Emp_record
SQL*Plus 替代變量 P_name P_sal
綁定變量 G_name G_year_sal
PL/SQL 變量類型

在前面的介紹中舶担,有系統(tǒng)的數(shù)據(jù)類型坡疼,也可以自定義數(shù)據(jù)類型。下表是 ORACLE 類型和 PL/SQL 中的變量類型的合法使用列表:

  • 變量類型

在 ORACLE8i 中可以使用的變量類型有:


  • 復(fù)合類型

ORACLE 在 PL/SQL 中除了提供象前面介紹的各種類型外,還提供一種稱為復(fù)合類型的類型---記錄和表.

  • 記錄類型
    記錄類型是把邏輯相關(guān)的數(shù)據(jù)作為一個單元存儲起來衣陶,稱作 PL/SQL RECORD 的域(FIELD)柄瑰,其作用是存放互不相同但邏輯相關(guān)的信息。
    定義記錄類型語法如下:
 TYPE record_type IS RECORD(    
   Field1 type1  [NOT NULL]  [:= exp1 ],    
   Field2 type2  [NOT NULL]  [:= exp2 ],    
   . . .   . . .    
   Fieldn typen  [NOT NULL]  [:= expn ] ); 

例 1 :

declare
     type test_rec is record(          
          l_name varchar2(30),
          d_id number(4));
     v_emp test_rec;
begin
     v_emp.l_name := 'Tom';
     v_emp.d_id :=1234;
     dbms_output.put_line(v_emp.l_name || ',' || v_emp.d_id);
end;
declare
     type test_rec is record(          
          l_name varchar2(30),
          d_id number(4));
     v_emp test_rec;
begin
     select last_name,department_id into v_emp
     from employees
     where employee_id = 200;
     dbms_output.put_line(v_emp.l_name || ',' || v_emp.d_id);
end;

提示
1.DBMS_OUTPUT.PUT_LINE 過程的功能類似于 Java 中的 System.out.println() 直接將輸出結(jié)果送到標(biāo)準(zhǔn)輸出中 .
2.在使用上述過程之前必須將 SQL * PLUS 的環(huán)境參數(shù) SERVEROUTPUT
設(shè)置為 ON, 否則將看不到輸出結(jié)果 : set serveroutput on
3.可以用 SELECT 語句對記錄變量進(jìn)行賦值,只要保證記錄字段與查詢結(jié)果列表中的字段相配即可剪况。

  • 使用%TYPE
    定義一個變量教沾,其數(shù)據(jù)類型與已經(jīng)定義的某個數(shù)據(jù)變量的類型相同,或者與數(shù)據(jù)庫表的某個列的數(shù)據(jù)類型 相同译断,這時可以使用%TYPE授翻。
    使用%TYPE 特性的優(yōu)點(diǎn)在于:
    1.所引用的數(shù)據(jù)庫列的數(shù)據(jù)類型可以不必知道;

2.所引用的數(shù)據(jù)庫列的數(shù)據(jù)類型可以實時改變。

declare
     type test_rec is record(          
          l_name employee.last_name%type,
          d_id employee.department_id%type);
     v_emp test_rec;
begin
     select last_name,
     department_id into v_emp
     from employees  where employee_id = 200;
     dbms_output.put_line(v_emp.l_name || ',' || v_emp.d_id);
end;
  • 使用%ROWTYPE
    PL/SQL 提供%ROWTYPE 操作符, 返回一個記錄類型, 其數(shù)據(jù)類型和數(shù)據(jù)庫表的數(shù)據(jù)結(jié)構(gòu)相一致堪唐。
    使用%ROWTYPE 特性的優(yōu)點(diǎn)在于:
    1.所引用的數(shù)據(jù)庫中列的個數(shù)和數(shù)據(jù)類型可以不必知道巡语;
    2.所引用的數(shù)據(jù)庫中列的個數(shù)和數(shù)據(jù)類型可以實時改變。
declare
     v_emp employee%rowtype;
begin
     select * into v_emp
     from employees where employee_id = 200;
     dbms_output.put_line(v_emp.last_name || ',' || v_emp.department_id || ',' || v_emp.hire_date);
end;
  • PL/SQL 表(嵌套表)
    PL/SQL 程序可使用嵌套表類型創(chuàng)建具有一個或多個列和無限行的變量, 這很像數(shù)據(jù)庫中的表. 聲明嵌 套表類型的一般語法如下:
TYPE type_name IS TABLE OF  
{datatype | {variable | table.column} % type | table%rowtype}; 
declare
     type dep_table_type is table of departments%rowtype;
     my_dep_table dep_table_type := dep_table_type();
begin
     my_dep_table.extend(5);
    
     for i in 1 .. 5 loop
     select * from departments
     where department_id = 200 + 10 * i;
     end loop;

     dbms_output.put_line(my_dep_table.count());
     dbms_output.put_line(my_dep_table(1).department_id);
end;

說明
1.在使用嵌套表之前必須先使用該集合的構(gòu)造器初始化它. PL/SQL 自動提供一個帶有相同名字的構(gòu)造器作為集合類型.
2.嵌套表可以有任意數(shù)量的行. 表的大小在必要時可動態(tài)地增加或減少: extend(x) 方法添加 x 個空元素到集合末尾; trim(x) 方法為去掉集合末尾的 x 個元素.

運(yùn)算符和表達(dá)式(數(shù)據(jù)定義)
  • 關(guān)系運(yùn)算符
運(yùn)算符 意義
= 等于
<> , != , ~= , ^= 不等于
< 小于
> 大于
<= 小于或等于
>= 大于或等于
  • 一般運(yùn)算符
運(yùn)算符 意義
+ 加號
- 減號
* 乘號
/ 除號
:= 賦值號
=> 關(guān)系號
.. 范圍運(yùn)算符
|| 字符連接符
  • 邏輯運(yùn)算符
運(yùn)算符 意義
IS NULL 是空值
BETWEEN AND 介于兩者之間
IN 在一列值中間
AND 邏輯與
OR 邏輯或
NOT 取返,如 IS NOT NULL, NOT IN
變量賦值

在 PL/SQL 編程中淮菠,變量賦值是一個值得注意的地方男公,它的語法如下:

variable  := expression ;    

variable 是一個 PL/SQL 變量, expression 是一個 PL/SQL 表達(dá)式.

  • 字符及數(shù)字運(yùn)算特點(diǎn)

空值加數(shù)字仍是空值:NULL + < 數(shù)字> = NULL
空值加(連接)字符,結(jié)果為字符:NULL || <字符串> = < 字符串>

  • BOOLEAN 賦值

布爾值只有 TRUE, FALSE 及 NULL 三個值兜材。

  • 數(shù)據(jù)庫賦值

數(shù)據(jù)庫賦值是通過 SELECT語句來完成的理澎,每次執(zhí)行 SELECT語句就賦值一次,一般要求被賦值的變量與 SELECT中的列名要一一對應(yīng)曙寡。如:

DECLARE 
     emp_id    emp.empno%TYPE :=7788; 
     emp_name emp.ename%TYPE; 
     wages     emp.sal%TYPE; 
BEGIN 
     SELECT ename, NVL(sal,0) + NVL(comm,0) INTO emp_name, wages  
     FROM emp WHERE empno = emp_id;      
     DBMS_OUTPUT.PUT_LINE(emp_name||’----‘||to_char(wages)); 
END; 

提示: 不能將 SELECT 語句中的列賦值給布爾變量

  • 可轉(zhuǎn)換的類型賦值
  • CHAR 轉(zhuǎn)換為 NUMBER:
    使用 TO_NUMBER 函數(shù)來完成字符到數(shù)字的轉(zhuǎn)換糠爬,如:
    v_total := TO_NUMBER(‘100.0’) + sal;
  • NUMBER 轉(zhuǎn)換為 CHAR:
    使用 TO_CHAR 函數(shù)可以實現(xiàn)數(shù)字到字符的轉(zhuǎn)換,如:
    v_comm := TO_CHAR(‘123.45’) || ’元’ ;
  • 字符轉(zhuǎn)換為日期:
    使用 TO_DATE 函數(shù)可以實現(xiàn) 字符到日期的轉(zhuǎn)換举庶,如:
    v_date := TO_DATE('2001.07.03','yyyy.mm.dd');
  • 日期轉(zhuǎn)換為字符:
    使用 TO_CHAR 函數(shù)可以實現(xiàn)日期到字符的轉(zhuǎn)換执隧,如:
    v_to_day := TO_CHAR(SYSDATE, 'yyyy.mm.dd hh24:mi:ss') ;
變量作用范圍及可見性

在 PL/SQL 編程中,如果在變量的定義上沒有做到統(tǒng)一的話户侥,可能會隱藏一些危險的錯誤镀琉,這樣的原因 主要是變量的作用范圍所致。與其它高級語言類似蕊唐,PL/SQL 的變量作用范圍特點(diǎn)是:

  • 變量的作用范圍是在你所引用的程序單元(塊屋摔、子程序、包)內(nèi)替梨。即從聲明變量開始到該塊的結(jié)束钓试。
  • 一個變量(標(biāo)識)只能在你所引用的塊內(nèi)是可見的。
  • 當(dāng)一個變量超出了作用范圍副瀑,PL/SQL 引擎就釋放用來存放該變量的空間(因為它可能不用了)弓熏。
  • 在子塊中重新定義該變量后,它的作用僅在該塊內(nèi)糠睡。
注釋

在PL/SQL里挽鞠,可以使用兩種符號來寫注釋,即:

  • 使用雙 ‘-‘ ( 減號) 加注釋 PL/SQL允許用 – 來寫注釋狈孔,它的作用范圍是只能在一行有效信认。
    如: V_Sal NUMBER(12,2); -- 工資變量。
  • 使用 /* */ 來加一行或多行注釋均抽,如: /***********************************************/
    /* 文件名: department_salary.sql */ /***********************************************/
  • 提示:被解釋存放在數(shù)據(jù)庫中的 PL/SQL 程序嫁赏,一般系統(tǒng)自動將程序頭部的注釋去掉。只有在 PROCEDURE 之后的注釋才被保留到忽;另外程序中的空行也自動被去掉
簡單例子
  • 簡單數(shù)據(jù)插入例子
/* 本例子僅是一個簡單的插入橄教,不是實際應(yīng)用。  */ 
DECLARE 
      v_ename   VARCHAR2(20) := ‘Bill’; 
      v_sal       NUMBER(7,2) :=1234.56; 
      v_deptno   NUMBER(2) := 10; 
      v_empno   NUMBER(4) := 8888; 
BEGIN 
      INSERT INTO emp ( empno, ename, JOB, sal, deptno , hiredate )   
             VALUES ( v_empno, v_ename, ‘Manager’, v_sal, v_deptno,  
             TO_DATE(’1954.06.09’,’yyyy.mm.dd’) ); 
      COMMIT; 
END; 
  • 簡單數(shù)據(jù)刪除例子
/* 本例子僅是一個簡單的刪除例子喘漏,不是實際應(yīng)用护蝶。  */  
DECLARE 
     v_empno   number(4) := 8888; 
BEGIN 
     DELETE FROM emp WHERE empno=v_empno; 
     COMMIT; 
END; 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市翩迈,隨后出現(xiàn)的幾起案子持灰,更是在濱河造成了極大的恐慌,老刑警劉巖负饲,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件堤魁,死亡現(xiàn)場離奇詭異,居然都是意外死亡返十,警方通過查閱死者的電腦和手機(jī)妥泉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洞坑,“玉大人盲链,你說我怎么就攤上這事〕僭樱” “怎么了刽沾?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長排拷。 經(jīng)常有香客問我侧漓,道長,這世上最難降的妖魔是什么监氢? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任布蔗,我火速辦了婚禮,結(jié)果婚禮上忙菠,老公的妹妹穿的比我還像新娘何鸡。我一直安慰自己,他們只是感情好牛欢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布骡男。 她就那樣靜靜地躺著,像睡著了一般傍睹。 火紅的嫁衣襯著肌膚如雪隔盛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天拾稳,我揣著相機(jī)與錄音吮炕,去河邊找鬼。 笑死访得,一個胖子當(dāng)著我的面吹牛龙亲,可吹牛的內(nèi)容都是我干的陕凹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鳄炉,長吁一口氣:“原來是場噩夢啊……” “哼杜耙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拂盯,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤佑女,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后谈竿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體团驱,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年空凸,在試婚紗的時候發(fā)現(xiàn)自己被綠了嚎花。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡呀洲,死狀恐怖贩幻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情两嘴,我是刑警寧澤丛楚,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站憔辫,受9級特大地震影響趣些,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贰您,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一坏平、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锦亦,春花似錦舶替、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至抛蚁,卻和暖如春陈醒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瞧甩。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工钉跷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肚逸。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓爷辙,卻偏偏與公主長得像彬坏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子膝晾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355