官术网_书友最值得收藏!

  • Oracle從新手到高手
  • 楊繼萍
  • 3723字
  • 2019-12-09 14:49:09

6.1 PL/SQL結(jié)構(gòu)

PL/SQL稱為過程化SQL語言(Procedural Language/SQL),是一種程序語言,也是Oracle數(shù)據(jù)庫對SQL語句的擴展,在其基礎(chǔ)上增加了編程語言的特點。

PL/SQL語言是將數(shù)據(jù)操作和查詢語句組織在PL/SQL代碼的過程性單元中,通過邏輯判斷、循環(huán)等操作,實現(xiàn)復(fù)雜的功能或者計算的程序語言。

6.1.1 PL/SQL概述

由于SQL只是一種聲明式語言,它沒有流程控制,也不存在變量,只有表或者列,所以不能將某個SQL語句的執(zhí)行結(jié)果傳遞給另外一個語句。為了實現(xiàn)該目的,用戶不得不使用一條更復(fù)雜的語句。而且,SQL語句中更沒有可以控制程序流程的IF或LOOP語句。

PL/SQL是過程化的結(jié)構(gòu)查詢語言(Procedural Language/Structured Query Language),它可以彌補SQL語句的不足。在PL/SQL中可以通過IF和LOOP語句控制程序的執(zhí)行流程,并且可以定義變量,以便利用這些變量在語句之間傳遞數(shù)據(jù)信息。PL/SQL是Oracle的專用語言,它是對標準SQL語言的擴展,并且SQL語句可以嵌套在PL/SQL程序代碼中,將SQL的數(shù)據(jù)處理能力和PL/SQL的過程處理能力結(jié)合在一起。

在Oracle數(shù)據(jù)庫內(nèi)置了PL/SQL處理引擎,常用的開發(fā)工具是Oracle附帶的SQL*Plus。實際上,SQL*Plus只是用于將SQL語句或PL/SQL程序發(fā)送到數(shù)據(jù)庫,并將處理后的結(jié)果顯示在屏幕上的工具,并且用戶也可以選擇其他的工具運算SQL和PL/SQL程序。

PL/SQL程序的基本結(jié)構(gòu)稱為“塊”,每個塊都包含了PL/SQL語句和SQL語句。典型的PL/SQL塊的結(jié)構(gòu)如下:

      [declare
      declareation_statements]
      begin
      executable_statements
      [exception
      exception_handing_statements]
      end;

PL/SQL程序塊中的每一條語句都必須以分號結(jié)束,SQL語句可以是多行的,但分號表示該語句的結(jié)束。一行中可以有多條SQL語句,但是它們之間必須以分號分隔。PL/SQL程序的注釋用“--”表示。

從上面的語法規(guī)則中可以發(fā)現(xiàn),一個PL/SQL程序塊分為3部分:聲明部分、執(zhí)行部分和異常處理部分。聲明部分是可選的,它由關(guān)鍵字DECLARE開始,到關(guān)鍵字BEGIN結(jié)束。在這部分可以聲明一些PL/SQL變量、常量、游標和異常的定義等。當基本塊結(jié)束后,聲明部分中的所有內(nèi)容均不復(fù)存在。在某個基本塊中所聲明的內(nèi)容只能在該塊中使用,其他的基本塊不能使用。

執(zhí)行部分以關(guān)鍵字BEGIN開始,可以以兩種不同的方式結(jié)束。如果存在異常處理,則以關(guān)鍵字EXCEPTION結(jié)束。如果沒有使用異常處理,則以關(guān)鍵字END結(jié)束。在執(zhí)行部分包含多個PL/SQL語句和SQL語句。

在PL/SQL語句的執(zhí)行過程中,由于各種原因會產(chǎn)生一些錯誤,這些錯誤的發(fā)生會導(dǎo)致程序被迫中斷運行。這樣PL/SQL程序開發(fā)人員就必須設(shè)法向用戶發(fā)出一些有用的出錯信息,或者在錯誤發(fā)生后采取某些措施進行糾正并繼續(xù)運行程序。另外,所有相關(guān)數(shù)據(jù)庫操作可能需要回退到異常產(chǎn)生之前的狀況,這就需要在PL/SQL程序中提供異常處理能力。

PL/SQL的異常處理部分是以關(guān)鍵字EXCEPTION開始的,它的結(jié)束就是整個基本塊的結(jié)束。每個異常均由WHEN語句開頭,接著就是這種異常出現(xiàn)時相應(yīng)的處理動作。

為了更好地理解PL/SQL程序,下面將通過一個具體的實例介紹PL/SQL的結(jié)構(gòu)特點,使用戶對PL/SQL程序的特點有一個感性的認識。

在上面的程序中,為了在服務(wù)器端顯示執(zhí)行結(jié)果,使用了SET SERVEROUTPUT ON命令。在DECLARE關(guān)鍵字表示的聲明塊中聲明了3個變量—A、B和C,其數(shù)據(jù)類型為NUMBER,并且為變量A和B賦予了初始值3和4。

接下來以BEGIN關(guān)鍵字標識可執(zhí)行塊的開始,在可執(zhí)行塊中包含了兩條PL/SQL語句。第一條語句計算A*B/(A+B)的值,并將計算值賦予變量C;隨后的語句則使用DBMS_OUTPUT. PUT_LINE(C);語句顯示計算結(jié)果。EXCEPTION關(guān)鍵字表示異常處理塊的開始。在這里捕獲的異常是ZERO_DIVIDE,表示出現(xiàn)了除數(shù)為0的錯誤。出現(xiàn)錯誤時顯示的錯誤信息為“除數(shù)不能為0!”

6.1.2 PL/SQL變量的聲明

變量本質(zhì)上是一種用名稱進行標記的容器,它們可以包含或保存不同類型的數(shù)據(jù)。根據(jù)不同的數(shù)據(jù)類型,變量可以存儲不同類型的數(shù)據(jù),并且可以彼此通過變量名進行區(qū)分。

可以使用下面兩種語法聲明PL/SQL變量:

      variable_name data_type [ [NOT NULL]:=default_value_expression];
      variable_name data_type [ [NOT NULL] DEFAULT default_value_expression];

變量名variable_name可以是任何合法的PL/SQL標識符,合法的PL/SQL標識符必須滿足如下條件。

※ 長度不能超過30個字符,而且中間不能有空格。

※ 由字母、0~9的數(shù)字、下畫線“_”、美元符號“$”以及符號“#”組成。

※ 必須以字母開始。

※ 不能使用PL/SQL或SQL中的關(guān)鍵字。例如,BEGIN、END不能作為變量名,因為它在PL/SQL程序中有特殊的意義(表示塊的開始和結(jié)束)。

可以在SQL*Plus使用如下命令獲得SQL和PL/SQL中的關(guān)鍵字。

     help reserved words

變量類型DATA_TYPE必須是合法的SQL或PL/SQL數(shù)據(jù)類型,變量的類型決定了其中存儲的數(shù)據(jù)類型。如果變量只能存儲一個單獨的值,則該變量稱為“標量變量”。如果變量中可以存儲多個值(如表中一行記錄),則該變量稱為“復(fù)合類型的變量”。

標量變量所使用的數(shù)據(jù)類型包括字符、數(shù)字、日期和布爾類型等,標量變量所使用的數(shù)據(jù)類型見下表所示。

NOT NULL表示變量必須是非空的,需要指定初始值。當變量被創(chuàng)建后,可以以值表達式的方式對其賦初始值。在聲明變量時,還可以使用DEFAULT關(guān)鍵字指定變量的默認值,這樣如果未向變量賦值時,變量的值就是設(shè)置的默認值。

下面介紹幾種常用的數(shù)據(jù)類型,這些常用的數(shù)據(jù)類型包括NUMBER、VARCHAR2、DATE和BOOLEAN等。

VARCHAR2是一種變長的數(shù)據(jù)類型。在PL/SQL中,該類型的最大長度為32767。VARCHAR2類型變量的語法形式如下所示。

     char_variable varchar2(max_length);

其中,MAX_LENGTH參數(shù)是正整數(shù),表示該變量最大可以容納的字符數(shù)。

NUMBER數(shù)據(jù)類型表示所有的數(shù)字數(shù)據(jù),聲明NUMBER數(shù)據(jù)類型變量的格式如下所示。

     number_variable number(length,decimal_places);

其中,LENGTH參數(shù)的取值范圍為1~38,DECIMAL_PLACES參數(shù)用于指定數(shù)字的小數(shù)點后面的位數(shù)。

DATE數(shù)據(jù)類型用于存儲日期數(shù)據(jù)和時間數(shù)據(jù),聲明該類型變量的格式如下所示。

     date_variable date;

BOOLEAN數(shù)據(jù)類型用于聲明布爾值,該類型的變量只能存儲TRUE、FALSE或NULL值。

下面的代碼在程序塊的定義部分聲明了4種類型的變量。

這些標量變量只可以在該程序塊中使用,并且在BEGIN部分開始執(zhí)行前,每個變量都將包含一個NULL值。

6.1.3 %TYPE變量

在聲明變量時,除了可以使用Oracle規(guī)定的數(shù)據(jù)類型外,還可以使用%TYPE關(guān)鍵字定義變量類型。%TYPE關(guān)鍵字的含義是聲明一個與指定列名稱相同的數(shù)據(jù)類型。例如,下面的語句聲明了一個與EMP表中ENAME列完全相同的數(shù)據(jù)類型。

      declare
      var_name emp.ename%type;

如果ENAME列的數(shù)據(jù)類型為VARCHAR2(40),那么變量VAR_NAME的數(shù)據(jù)類型就是VARCHAR2(40)。

下面的示例演示了如何使用%TYPE類型的變量從數(shù)據(jù)庫中檢索數(shù)據(jù)。

在上面的PL/SQL程序中,主要使用了SELECT語句從EMP中檢索數(shù)據(jù)。該SELECT語句與前面使用的SQL查詢語句非常相似,唯一不同之處在于它多了一個INTO子句。INTO子句跟在SELECT子句后,表示從數(shù)據(jù)庫檢索的數(shù)值將保存在哪個變量中。

提示:

需要注意的是,因為定義的變量只可以存儲一個單獨的值,所以使用WHERE子句限定返回結(jié)果集中只包含一行數(shù)據(jù)。如果返回的結(jié)果集中包含多行數(shù)據(jù),則由于實際返回的行數(shù)超出請求的行數(shù)而產(chǎn)生錯誤。

使用%TYPE定義變量有兩個好處:首先,用戶不必查看表中各個列的數(shù)據(jù)類型,即可確保所定義的變量能夠存儲檢索的數(shù)據(jù);其次,如果對表的結(jié)構(gòu)進行修改(例如,改變某一個列的數(shù)據(jù)類型),那么用戶不必考慮對所定義的變量進行更改,而%TYPE類型的變量會自動調(diào)整。使用%TYPE類型的變量也有一個缺點,在程序的執(zhí)行過程中,系統(tǒng)必須查看數(shù)據(jù)字典,以確定變量的數(shù)據(jù)類型,因此它會對程序的性能產(chǎn)生影響。

提示:

對于剛接觸PL/SQL程序的用戶而言,經(jīng)常犯的一個錯誤就是遺漏賦值符號“:=”中的冒號,這就是PL/SQL程序與其他程序中賦值符號的區(qū)別。

6.1.4 復(fù)合變量

很多結(jié)構(gòu)化程序設(shè)計語言都提供了記錄類型的數(shù)據(jù)類型,在PL/SQL中,也支持將多個基本數(shù)據(jù)類型捆綁在一起的記錄數(shù)據(jù)類型,即復(fù)合變量。相對于標量變量,復(fù)合變量一次可以存儲多個數(shù)值。

對于復(fù)合變量,用戶可以根據(jù)需要定義其結(jié)構(gòu),可以使用由系統(tǒng)自動決定變量的結(jié)構(gòu)。下面列出了PL/SQL提供的幾種常用的復(fù)合類型。

※ 自定義記錄類型:在記錄類型的復(fù)合變量中可以存儲多個標量值,它的結(jié)構(gòu)通常與數(shù)據(jù)庫行相似。

※ %ROWTYPE類型:該類型的復(fù)合變量可以根據(jù)指定的表結(jié)構(gòu),由系統(tǒng)決定其結(jié)構(gòu)。

1. 自定義記錄類型

使用自定義記錄數(shù)據(jù)類型的變量可以存儲由多個列值組成的一行數(shù)據(jù)。當使用記錄類型的變量時,首先需要定義記錄的結(jié)構(gòu),然后才可以聲明記錄類型的變量。定義記錄數(shù)據(jù)類型時必須使用TYPE語句,在這個語句中指出將在記錄中包含的字段及其數(shù)據(jù)類型。使用TYPE語句定義記錄數(shù)據(jù)類型的語法形式如下。

      type record_name is record(
      field1_name  data_type  [not null] [:=default_value],
      ……
      fieldn_name data_type [not null] [:=default_value]);

在上面的語句中,RECORD_NAME為自定義的記錄數(shù)據(jù)類型名,例如數(shù)值數(shù)據(jù)類型的名稱為NUMBER。FILED1_NAME為記錄數(shù)據(jù)類型中的字段名,DATA_TYPE為該字段的數(shù)據(jù)類型,從這里可以看出,字段的聲明與標量變量的聲明類似。

下面的程序代碼定義了名為EMPLOYEE_TYPE的記錄類型,該記錄類型由整數(shù)型的NO_ NUMBER、字符型的NAME_STRING和整數(shù)的SAL_NUMBER基本類型變量組成,EMPLOYEE是該類型的變量,引用記錄型變量的方法是“記錄變量名.字段名”。

程序的執(zhí)行部分是從SCOTT.EMP數(shù)據(jù)表中提取EMPNO列為7369的記錄,并將數(shù)據(jù)存放在復(fù)合變量EMPLOYEE中,然后輸出復(fù)合變量的各個字段值,實際上就是數(shù)據(jù)表中相應(yīng)記錄的值。

提示:

SELECT語句檢索的列是以固定的順序賦予記錄變量中各個字段。即查詢的第一個列值賦予記錄變量中第一個字段,第二個列值賦予記錄變量的第二個字段。因此,在SELECT語句查詢的列值數(shù)量和順序中,用戶必須與定義記錄類型中定義的字段數(shù)量和順序相匹配。

如果兩個記錄變量的數(shù)據(jù)類型相同,那么可以將記錄變量中的值直接賦予另一個記錄變量。如果記錄數(shù)據(jù)類型不同,那么無論記錄類型的結(jié)構(gòu)是否相同,都不可以直接將一個記錄變量賦予另一個記錄變量。

2. %ROWTYPE類型變量

與%TYPE類型的變量和自定義記錄類型變量相比,%ROWTYPE類型的變量結(jié)合了這兩者的特點,它可以根據(jù)數(shù)據(jù)表中行的結(jié)構(gòu)定義數(shù)據(jù)類型,用于存儲從數(shù)據(jù)表中檢索到的一行數(shù)據(jù)。下面的示例,使用%ROWTYPE類型的變量存儲查詢的數(shù)據(jù)。

在上面的程序中定義了一個%ROWTYPE類型的變量,該變量的結(jié)構(gòu)與EMP表的結(jié)構(gòu)完全相同。因此,可以將檢索到的一行數(shù)據(jù)保存到該類型的變量中,并且根據(jù)表中列的名稱引用對應(yīng)的數(shù)值。

主站蜘蛛池模板: 游戏| 商城县| 荃湾区| 乌鲁木齐市| 临澧县| 建瓯市| 理塘县| 遵化市| 沈丘县| 泾川县| 东丰县| 博兴县| 荥经县| 沙河市| 巩义市| 淮滨县| 岱山县| 汝城县| 平昌县| 济阳县| 广灵县| 垦利县| 东乌珠穆沁旗| 休宁县| 左云县| 左贡县| 贵阳市| 万宁市| 襄樊市| 冀州市| 北京市| 蕲春县| 山东| 宜丰县| 卓资县| 聂荣县| 泸西县| 郁南县| 墨江| 长治县| 黑山县|