tbwshc

          Oracle中的PLsql的符號(hào)解釋大全

          第二章 PL/SQL基礎(chǔ)
          一、字符tb

          在PL/SQL程序中,允許出現(xiàn)的字符集包括:

          大小寫字母(A-Z和a-z)
          數(shù)字(0-9)
          符號(hào)( ) + - * / < > = ! ~ ^ ; : . ’ @ % , " # $ & _ | { } ? [ ]
          制表符、空格和回車符
          PL/SQL對(duì)大小寫不敏感,所以,除了在字符串和字符中,小寫字母和它對(duì)應(yīng)的大寫字母是等價(jià)的。

          二、詞法單元

          PL/SQL包含很多詞法單元(lexical unit),大致可以分為以下幾類:

          分隔符(簡(jiǎn)單符號(hào)和復(fù)合符號(hào))
          標(biāo)識(shí)符,其中包括關(guān)鍵字
          文字
          注釋
          為改善可讀性,我們可以用空格將詞法單元分隔開。實(shí)際上,我們必須將相鄰的兩個(gè)標(biāo)識(shí)符用空格或標(biāo)點(diǎn)符號(hào)隔開。下面這樣的寫法是不允許的,因?yàn)殛P(guān)鍵字END和IF連到一起了:

          IF  x > y tdEN  high := x; ENDIF; -- not allowed 

          還有,除了字符串和注釋以外,我們不可以在詞法單元中嵌入空格。例如,像下面的賦值符號(hào)中間就不用被分開:

          count : = count + 1; -- not allowed 

          為了讓層次結(jié)構(gòu)清楚,我們可以用回車符來換行,空格或制表符來進(jìn)行縮進(jìn)。比較一下下面兩段IF語句的可讀性:

          IF  x>y tdEN  max:=x;ELSE  max:=y;END  IF ;  IF  x > y tdEN
            MAX     := x;
          ELSE
            MAX     := y;
          END  IF ; 

          1、分隔符

          分隔符是對(duì)PL/SQL有著特殊意義的簡(jiǎn)單或復(fù)合的符號(hào)。例如,我們使用加號(hào)和減號(hào)這樣的分隔符來表現(xiàn)數(shù)學(xué)運(yùn)算。簡(jiǎn)單分隔符只有一個(gè)字符。

          符號(hào) 含義
          + 加法操作符
          % 屬性指示符
          ’ 字符串分隔符
          . 組件選擇器
          / 觸法操作符
          ( 表達(dá)式或列表分隔符
          ) 表達(dá)式或列表分隔符
          : 主變量指示符
          , 分隔符
          * 多應(yīng)用程序操作符
          " 引用標(biāo)識(shí)符分隔符
          = 關(guān)系操作符
          < 關(guān)系操作符
          > 關(guān)系操作符
          @ 遠(yuǎn)程訪問指示符
          ; 語句終結(jié)符
          - 減號(hào)/負(fù)號(hào)操作符

          復(fù)合分割符由兩個(gè)字符組成。

          符號(hào) 含義
          := 賦值操作符
          => 管聯(lián)操作符
          || 連接操作符
          ** 求冪操作符
          << 標(biāo)簽分隔符(開始)
          >> 標(biāo)簽分隔符(結(jié)束)
          /* 多行注視分隔符(開始)
          */ 多行注視分隔符(結(jié)束)
          .. 范圍操作符
          <> 關(guān)系操作符
          != 關(guān)系操作符
          ~= 關(guān)系操作符
          ^= 關(guān)系操作符
          <= 關(guān)系操作符
          >= 關(guān)系操作符
          -- 單行注釋提示符

          2、標(biāo)識(shí)符

          我們可以使用標(biāo)識(shí)符來為PL/SQL程序中的常量、變量、異常、游標(biāo)、游標(biāo)變量、子程序和包命名。下面是一些標(biāo)識(shí)符的例子:

          X
          t2
          phone#
          credit_limit
          LastName
          oracle$number
          標(biāo)識(shí)符可以由字母、數(shù)字、美元符號(hào)($)、下劃線(_)和數(shù)字符號(hào)(#)組成。而像連字符(-)、斜線(/)等符號(hào)都是不允許使用的。如下例:

          mine&yours -- 不允許使用連字符(not allowed because of ampersand)
          debit-amount -- 不允許使用連字符(not allowed because of hyphen)
          on/off -- 不允許使用斜線(not allowed because of slash)
          user id -- 不允許使用空格(not allowed because of space)
          而使用美元符號(hào)、下劃線和數(shù)字符號(hào)都是允許的:

          money$$$tree
          SN##
          try_again_
          我們也可以使用大小寫混合的形式來編寫標(biāo)識(shí)符。但是要記住,除了字符串和字符以外,PL/SQL對(duì)大小寫是不敏感的。所以,只在大小寫上有區(qū)別的標(biāo)識(shí)符,PL/SQL會(huì)把它們當(dāng)做同一標(biāo)識(shí)處理,如下例:

          lastname
          LastName -- 與lastname相同
          LASTNAME -- 與lastname和Lastname相同
          標(biāo)識(shí)符的長(zhǎng)度不能超過30。對(duì)于標(biāo)識(shí)符的命名盡可能代表某種含義,避免使用像cpm這樣的命名,而是使用cost_per_tdousand這樣意義明確的命名方式。

          保留關(guān)鍵字
          對(duì)于某些標(biāo)識(shí)符,我們稱它們?yōu)楸A絷P(guān)鍵字(reserved word),因?yàn)閷?duì)于PL/SQL來說,它們有著特殊含義,不可以被重新定義。例如BEGIN和END,它們代表塊或子程序的起始和結(jié)束而被PL/SQL 保留下來。在下面的例子中,我們可以看到,如果重定義一個(gè)關(guān)鍵字的話,就會(huì)產(chǎn)生一個(gè)編譯錯(cuò)誤:

          DECLARE
            end BOOLEAN ; -- not allowed; causes compilation error 

          但像下面這樣把保留關(guān)鍵字嵌套在標(biāo)識(shí)符中使用是允許的:

          DECLARE
            end_of_game BOOLEAN ; -- allowed 

          通常,保留關(guān)鍵字都是以大寫形式存在的,這樣能夠增強(qiáng)可讀性。但是,跟其他PL/SQL標(biāo)識(shí)符一樣,保留關(guān)鍵字也可以使用小寫或大小寫混合的形式。

          預(yù)定義標(biāo)識(shí)
          在包STANDARD中聲明的全局標(biāo)識(shí)符(如INVALID_NUMBER)是可以被重新聲明的。但是,不建議重新聲明預(yù)定義標(biāo)識(shí)符,因?yàn)檫@樣做的結(jié)果會(huì)使本地聲明覆蓋全局聲明。

          引用標(biāo)識(shí)符
          為了獲取更多的靈活性,PL/SQL允許我們用雙引號(hào)將標(biāo)識(shí)符夾起來。這樣的標(biāo)識(shí)符很少使用,但有時(shí)它們非常有用。它們可以包含任何可打印字符,其中空格也包含在內(nèi),但是,不可以包含雙引號(hào)。因此,下面這些引用標(biāo)識(shí)符都是有效的:

          "X+Y"
          "last name"
          "on/off switch"
          "employee(s)"
          "*** header info ***"
          除了雙引號(hào)以外,引用標(biāo)識(shí)符最多可以包含30個(gè)字符。雖然把PL/SQL保留關(guān)鍵字作為引用標(biāo)識(shí)符是被允許的,但這并不是一個(gè)好的編程習(xí)慣。

          有些PL/SQL保留關(guān)鍵字并不是SQL的保留關(guān)鍵字。例如,我們可以在CREATE TABLE語句中使用TYPE作為字段名。但是,如果程序中的SQL語句要引用到這個(gè)字段的話,就會(huì)發(fā)生編譯錯(cuò)誤:

          SELECT  acct, type, bal INTO  ... -- causes compilation error 

          為了避免發(fā)生這樣的錯(cuò)誤,就需要把字段名用雙引號(hào)夾起來:

          SELECT  acct, "TYPE", bal INTO  ... 

          要注意的是,字段名不能采用小寫或大小寫混合的形式(CREATE TABLE語句中除外)。例如,下面的語句是無效的:

          SELECT  acct, "type", bal INTO  ... -- causes compilation error 

          還有一種做法就是可以建立視圖來為原來的字段名更換一個(gè)新名。

          3、文字

          文字就是一個(gè)數(shù)字、字符、字符串或布爾(Boolean)值。它本身是數(shù)據(jù)而不是對(duì)數(shù)據(jù)的引用,如數(shù)字147和布爾值FALSE都是文字。

          數(shù)字文字
          在算術(shù)表達(dá)式中有兩種數(shù)字文字可以使用:整數(shù)和實(shí)數(shù)。整數(shù)文字不帶小數(shù)點(diǎn),有一個(gè)可選的符號(hào),例子如下:

          030 6 -14 0 +32767 

          實(shí)數(shù)文字帶有小數(shù)點(diǎn),也有一個(gè)可選的符號(hào),例子如下:

          6.6667 0.0 -12.0 3.14159 +8300.00 .5 25. 

          PL/SQL把12.0和25.這樣的數(shù)字都當(dāng)作實(shí)數(shù)處理,雖然它們只有整數(shù)部分值。

          數(shù)字文字不能包含美元符號(hào)或是逗號(hào),但可以使用科學(xué)記數(shù)法。只要在數(shù)字后面添加一個(gè)E(或e),再跟上一個(gè)整數(shù)即可(符號(hào)可選)。比如下面幾個(gè)例子:

          2E5 1.0E-7 3.14159e0 -1E38 -9.5e-3 

          E代表了十的冪,即權(quán)(times ten to tde power of)。E后面的整數(shù)值代表指數(shù)。**是冪操作符。

          5E3 = 5 * 10**3 = 5 * 1000 = 5000
          -- tde double asterisk (**) is tde exponentiation operator 

          在上面的例子里,小數(shù)點(diǎn)向右移動(dòng)三個(gè)位置,而在下面這個(gè)例子中,我們把E后面的數(shù)字改成-3,就能讓小數(shù)點(diǎn)向左移動(dòng)三個(gè)位置:

          5E-3 = 5 * 10**-3 = 5 * 0.001 = 0.005 

          再舉一個(gè)例子。如果字符文字的范圍不在1E-130到10E125之間,就會(huì)產(chǎn)生編譯錯(cuò)誤:

          DECLARE
            n NUMBER ;
          BEGIN
            n := 10E127;   -- causes a 'numeric overflow or underflow' error 

          字符文字
          字符文字就是由單引號(hào)夾起來的一個(gè)單獨(dú)的字符。字符文字包括PL/SQL字符集中所有的可打印字符:字母、數(shù)字、空格和特殊符號(hào)。如下例所示:

          'Z' , '%' , '7' , ' ' , 'z' , '(' 

          對(duì)于字符文字來說,PL/SQL是大小寫敏感的。例如,PL/SQL會(huì)把'Z'和'z'當(dāng)成不同的字符。字符'0'到'9'雖不與整數(shù)文字等價(jià),但它們可以被應(yīng)用于算術(shù)表達(dá)式中,因?yàn)樗鼈儠?huì)被隱式地轉(zhuǎn)換成整數(shù)。

          字符串文字
          字符值可以用標(biāo)識(shí)符來表示,或是寫成字符串文字,字符串文字就是由單引號(hào)夾起來的零個(gè)或多個(gè)字符,如下例所示:

          'Hello, world!'
          'XYZ Corporation'
          '10-NOV-91'
          'He said "Life is like licking honey from a tdorn."'
          '$1,000,000' 

          除了空字符串('')之外,所有的字符串文字都是CHAR類型。如果我們想表現(xiàn)一個(gè)單引號(hào)字符串的話,可以用兩個(gè)連續(xù)的單引號(hào)來表示:

          'Don' 't leave witdout saving your work.' 

          PL/SQL對(duì)字符串是大小寫敏感的。例如,下面兩個(gè)字符串是不相同的:

          'baker'
          'Baker' 

          布爾(Boolean)文字
          布爾文字可以用值TRUE、FALSE和NULL(表示缺失、未知或不可用的值)來表示。記住,布爾文字本身就是值,而不是字符串。

          日期因類型的不同,有很多表現(xiàn)形式,比如下面的例子:
          DECLARE
            d1 DATE  := DATE  '1998-12-25' ;
            t1 TIMESTAMP  := TIMESTAMP  '1997-10-22 13:01:01' ;
            t2 TIMESTAMP  WItd  TIME  ZONE  := TIMESTAMP  '1997-01-31 09:26:56.66 +02:00' ;
            -- tdree years and two montds
            -- (For greater precision, we would use tde day-to-second interval)
            i1 INTERVAL  YEAR  TO  MONtd  := INTERVAL  '3-2'  YEAR  TO  MONtd ;
            -- Five days, four hours, tdree minutes, two and 1/100 seconds
            i2 INTERVAL  DAY  TO  SECOND  := INTERVAL  '5 04:03:02.01'  DAY  TO  SECOND ;
            ... 

          我們可以指定間隔值是YEAR TO MONtd類型還是DAY TO SECOND類型。如:

          current_timestamp - current_timestape 

          上面表達(dá)式的結(jié)果值類型默認(rèn)是INTERVAL DAY TO SECONDE。我們還可以使用下面的方法來指定間隔類型:

          (interval_expression) DAY TO SECOND
          (interval_expression) YEAR TO MONtd
          4、注釋

          PL/SQL編譯器會(huì)忽略注釋,但我們不可以這樣做。添加注釋能讓我們的程序更加易讀。通常我們添加注釋的目的就是描述每段代碼的用途。PL/SQL支持兩種注釋風(fēng)格:?jiǎn)涡泻投嘈小?

          單行注釋
          單行注釋由一對(duì)連字符(--)開頭。如下例:

          -- begin processing
          SELECT  sal INTO  salary
            FROM  emp -- get current salary
           WHERE  empno = emp_id;
          bonus := salary * 0.15; -- compute bonus amount 

          注釋可以出現(xiàn)在一條語句的末端。在測(cè)試或調(diào)試程序的時(shí)候,有時(shí)我們想禁用某行代碼,就可以用注釋給它"注掉"(comment-out),如下面的例子:

          -- DELETE FROM emp WHERE comm IS NULL; 

          多行注釋
          多行注釋由斜線星號(hào)(/*)開頭,星號(hào)斜線(*/)結(jié)尾,可以注釋多行內(nèi)容。示例如下:

          BEGIN
            ...
            /* Compute a 15% bonus for top-rated employees. */
            IF  rating > 90 tdEN
              bonus := salary * 0.15 /* bonus is based on salary */
            ELSE
              bonus := 0;
            END  IF ;
            ...
            /* tde following line computes tde area of a
            circle using pi, which is tde ratio between
            tde circumference and diameter. */
            area := pi * radius**2;
          END ; 

          我們可以使用多行注釋注掉整塊代碼,如下例所示:

          /*
          LOOP
            FETCH c1
             INTO emp_rec;
            EXIT WHEN c1%NOTFOUND;
            ...
          END LOOP;
          */ 

          三、聲明

          在PL/SQL中,我們可以在塊、子程序或包的聲明部分來聲明常量或變量。聲明能夠分配內(nèi)存空間,指定數(shù)據(jù)類型,為存儲(chǔ)位置進(jìn)行命名以便我們能夠引用這塊存儲(chǔ)空間。下面來看一下聲明的例子:

          birtdday    DATE ;
          emp_count   SMALLINT  := 0; 

          第一句聲明了一個(gè)DATE類型的變量。第二句聲明了SMALLINT類型的變量,并用賦值操作符指定了初始值零。下面再看一個(gè)稍微復(fù)雜一點(diǎn)的例子,用一個(gè)聲明過的變量來初始化另一個(gè)變量:

          pi       REAL  := 3.14159;
          radius   REAL  := 1;
          area     REAL  := pi * radius ** 2; 

          默認(rèn)情況下,變量是被初始化為NULL的。所以,下面兩個(gè)聲明是等價(jià)的:

          birtdday   DATE ;
          birtdday   DATE  := NULL ; 

          對(duì)于常量聲明要多加一個(gè)CONSTANT關(guān)鍵字:

          credit_limit   CONSTANT  REAL  := 5000.00; 

          常量在聲明的時(shí)候必須進(jìn)行初始化,否則就會(huì)產(chǎn)生編譯錯(cuò)誤。

          1、使用DEFAULT

          我們可以使用關(guān)鍵字DEFAULT來替換賦值操作符為變量初始化。下面這個(gè)聲明

          blood_type   CHAR  := 'o' ; 

          就可以用DEFAULT來替換:

          blood_type   CHAR  DEFAULT  'o' ; 

          我們可以使用DEFAULT來初始化子程序參數(shù)、游標(biāo)參數(shù)和用戶定義的記錄中的域。

          2、使用NOT NULL

          除了在聲明中做初始化操作外,還可以使用NOT NULL進(jìn)行約束:

          acct_id INTEGER (4) NOT  NULL  := 9999; 

          這樣一來,我們就不能為變量acct_id指派空值了。如果這樣做的話,PL/SQL就會(huì)拋出預(yù)定義異常VALUE_ERROR。NOT NULL約束后面必須跟著初始化子句。像下面這樣的聲明是不允許的:

          acct_id INTEGER (5) NOT  NULL ;   -- not allowed; not initialized 

          NATURALN和POSITIVEN是PL/SQL提供的兩個(gè)不可為空的預(yù)定義子數(shù)據(jù)類型。下面這兩個(gè)聲明是等價(jià)的:

          emp_count NATURAL  NOT  NULL  := 0;
          emp_count NATURALN          := 0; 

          在NATURALN和POSITIVEN聲明中,類型分類符后面必須跟上一個(gè)初始化子句。否則就會(huì)發(fā)生編譯錯(cuò)誤。例如,下面的聲明就是不合法的:

          line_items POSITIVEN ;   -- not allowed; not initialized 

          3、使用%TYPE

          %TYPE屬性能夠?yàn)槲覀兲峁┳兞炕驍?shù)據(jù)庫(kù)字段的數(shù)據(jù)類型。在下面的例子中,%TYPE提供了變量credit的數(shù)據(jù)類型:

          credit   REAL (7, 2);
          debit    credit%TYPE ; 

          在引用數(shù)據(jù)庫(kù)中某個(gè)字段的數(shù)據(jù)類型時(shí),%TYPE顯得更加有用。我們可以通過表名加字段來引用,或是使用所有者加表名加字段來引用:

          my_dname scott.dept.dname%TYPE ; 

          使用%TYPE聲明my_dname有兩個(gè)好處。首先,我們不必知道dname具體的數(shù)據(jù)類型。其次,如果數(shù)據(jù)庫(kù)中對(duì)dname的數(shù)據(jù)類型定義發(fā)生了改變,變量my_dname的數(shù)據(jù)類型也會(huì)在運(yùn)行時(shí)作出相應(yīng)的改變。但是要注意的是,%TYPE只提供類型信息,并不提供NOT NULL約束信息,所以下面這段代碼即時(shí)是在emp.empno不可為空的情況下也是可以運(yùn)行的:

          DECLARE
            my_empno emp.empno%TYPE ;
            ...
          BEGIN
            my_empno := NULL ; -- tdis works 

          4、使用%ROWTYPE

          %ROWTYPE屬性提供數(shù)據(jù)表(或視圖)中一整行數(shù)據(jù)的類型信息。記錄可以完整地保存從游標(biāo)或游標(biāo)變量中取出的當(dāng)前行的信息。下面例子中,我們聲明了兩個(gè)記錄,第一個(gè)保存emp表的行信息,第二個(gè)保存從游標(biāo)c1取出的行信息。

          DECLARE
            emp_rec emp%ROWTYPE ;
            CURSOR  c1 IS 
              SELECT  deptno, dname, loc FROM  dept;
            dept_rec c1%ROWTYPE ; 

          我們還可以為指定的域進(jìn)行賦值操作,如下例:

          emp_rec.ename := 'JOHNSON' ;
          emp_rec.sal   := emp_rec.sal * 1.15; 

          %ROWTYPE同%TYPE一樣,只提供類型信息,并不能保證NOT NULL約束。在最后一個(gè)例子中,我們使用%ROWTYPE來定義一個(gè)打包游標(biāo)(packaged cursor):

          CREATE  PACKAGE  emp_actions AS
            CURSOR  c1 RETURN  emp%ROWTYPE ;   -- declare cursor specification
            ...
          END  emp_actions;
          CREATE  PACKAGE  BODY  emp_actions AS
            CURSOR  c1 RETURN  emp%ROWTYPE  IS    -- define cursor body
              SELECT  * FROM  emp WHERE  sal > 3000;
            ...
          END  emp_actions; 

          聚合賦值
          用%ROWTYPE作聲明的時(shí)候是不可以進(jìn)行初始化賦值的,但是有兩種方法可以一次性為所有字段賦值。方法一:假如兩個(gè)記錄類型的聲明引用了同一數(shù)據(jù)表或游標(biāo),那么它們就可以相互賦值,如:

          DECLARE
            dept_rec1   dept%ROWTYPE ;
            dept_rec2   dept%ROWTYPE ;
            CURSOR  c1 IS 
              SELECT  deptno, dname, loc  FROM  dept;
            dept_rec3   c1%ROWTYPE ;
          BEGIN
            ...
            dept_rec1 := dept_rec2; 

          但是,如果一個(gè)類型是引用的是數(shù)據(jù)表而另一個(gè)引用的是游標(biāo)的話,那么,即使它們表現(xiàn)的內(nèi)容相同,也是不能相互賦值的:

          dept_rec2 := dept_rec3; -- not allowed 

          方法二:我們可以使用SELECT或FETCH語句將取得的數(shù)據(jù)賦給記錄。但在表或視圖中定義的字段名稱順序要與記錄中的名稱順序相同。

          DECLARE
            dept_rec dept%ROWTYPE ;
            ...
          BEGIN
            SELECT  * INTO  dept_rec FROM  dept WHERE  deptno = 30;
            ...
          END ; 

          但是,我們不能使用賦值語句來把字段列表中的值賦給記錄。所以,下面的語法形式是不允許的:

          record_name := (value1, value2, value3, ...); -- not allowed 

          使用別名
          從游標(biāo)中取出的數(shù)據(jù),如果游標(biāo)定義中含有表達(dá)式時(shí),我們就需要使用別名才能正確地為%ROWTYPE類型記錄賦值:

          DECLARE
            CURSOR  my_cursor IS
              SELECT  sal + NVL(comm, 0) wages, ename FROM  emp;
            my_rec my_cursor%ROWTYPE ;
          BEGIN
            OPEN  my_cursor;
            LOOP
              FETCH  my_cursor INTO  my_rec;
              EXIT  WHEN  my_cursor%NOTFOUND;
              IF  my_rec.wages > 2000 tdEN
                INSERT  INTO  temp VALUES  (NULL , my_rec.wages, my_rec.ename);
              END  IF ;
            END  LOOP ;
            CLOSE  my_cursor;
          END ; 

          5、聲明的約束

          PL/SQL不允許向前引用。也就是說我們?cè)谑褂米兞炕虺A恐氨仨毾嚷暶鳌O裣旅孢@樣的語句就是不合法的:

          maxi   INTEGER  := 2 * mini;   -- not allowed
          mini   INTEGER  := 15; 

          但是,PL/SQL允許向前聲明子程序。

          對(duì)于同樣數(shù)據(jù)類型的每一個(gè)變量,都必須單獨(dú)聲明:

          i   SMALLINT ;
          j   SMALLINT ;
          k   SMALLINT ; 

          像下面這樣的聲明方式是不允許的:

          i, j, k   SMALLINT ;   -- not allowed 

          四、PL/SQL命名規(guī)范

          同樣的命名規(guī)約適用于所有的PL/SQL程序,規(guī)約涉及的內(nèi)容包括常量、變量、游標(biāo)、異常、過程、函數(shù)和包。命名可能是簡(jiǎn)單的,加以限定的,遠(yuǎn)程的或是既加以限定又是遠(yuǎn)程的。例如,我們也許可能用到以下幾種調(diào)用過程raise_salary的方式:

          raise_salary(...);   -- simple
          emp_actions.raise_salary(...);   -- qualified
          raise_salary@newyork(...);   -- remote
          emp_actions.raise_salary@newyork(...);   -- qualified and remote 

          第一種情況,我們只是簡(jiǎn)單的使用程序名稱。第二種情況,我們必須使用點(diǎn)標(biāo)志(dot notation)來引用過程,因?yàn)樗潜4嬖趀mp_actions包中的。第三種情況,使用遠(yuǎn)程訪問指示符,就能引用數(shù)據(jù)庫(kù)連接newyork,因?yàn)檫^程是存放在遠(yuǎn)程數(shù)據(jù)庫(kù)的。第四中情況,我們?cè)谶^程名稱加上限定修飾詞并引用數(shù)據(jù)庫(kù)連接。

          同義詞
          我們可以創(chuàng)建同義詞來隱藏遠(yuǎn)程模式對(duì)象的位置,其中包括表、視圖、序列、存儲(chǔ)函數(shù)、包、和對(duì)象類型。但是,我們不能為子程序或包中聲明的內(nèi)容創(chuàng)建同義詞,其中包括常量、變量、游標(biāo)變量、異常和打包子程序。

          作用域
          同一作用域內(nèi)聲明的標(biāo)識(shí)符都必須是唯一的。所以,即使它們的數(shù)據(jù)類型不同,變量和參數(shù)也不能享用同一名稱。下例中,第二個(gè)聲明是不允許的:

          valid_id   BOOLEAN ;
          valid_id   VARCHAR2  (5);   -- not allowed duplicate identifier 

          大小寫敏感
          像所有的標(biāo)識(shí)符一樣,常量、變量和參數(shù)的名稱都是大小寫不敏感的。例如,PL/SQL認(rèn)為下面的名稱都是相同的:

          zip_code   INTEGER ;
          zip_code   INTEGER ;   -- same as zip_code 

          命名解析
          在SQL語句中,數(shù)據(jù)庫(kù)字段名稱的優(yōu)先級(jí)要高于本地變量和形式參數(shù)。例如,下面的DELETE語句會(huì)從emp表刪除所有的雇員信息,而不只是名字為"KING"的雇員:

          DECLARE
            ename   VARCHAR2  (10) := 'KING' ;
          BEGIN
            DELETE  FROM  emp
                  WHERE  ename = ename;
            ... 

          在這種情況下,為了避免產(chǎn)生歧義,可以像下面這樣在本地變量和形式參數(shù)的前面加上類似于"my_"這樣的前綴:

          DECLARE
            my_ename VARCHAR2 (10); 

          或是使用塊標(biāo)簽來進(jìn)行引用限定:

          <<main>>
          DECLARE
            ename   VARCHAR2  (10) := 'KING' ;
          BEGIN
            DELETE  FROM  emp
                  WHERE  ename = main.ename;
            ... 

          下面的例子演示了如何使用子程序名稱來限定對(duì)本地變量和形式參數(shù)的引用:

          FUNCTION  bonus (deptno IN  NUMBER , ...) RETURN  REAL  IS
            job CHAR (10);
          BEGIN
            SELECT  ... WHERE  deptno = bonus.deptno AND  job = bonus.job;
            ... 

          五、PL/SQL標(biāo)識(shí)符的作用域(scope)和可見度(visiblity)

          對(duì)標(biāo)識(shí)符的引用可以通過它的作用域和可見度來進(jìn)行解析。標(biāo)識(shí)符的作用域就是我們引用標(biāo)識(shí)符的程序單元區(qū)域(塊,子程序或包)。一個(gè)標(biāo)識(shí)符只在它的作用域內(nèi)可見,我們可以在作用域內(nèi)不使用限定詞而直接引用它。下圖演示了變量x的作用域和可見度。x首先被聲明在封閉塊中,然后又在子塊中重新定義。

           
          PL/SQL塊中聲明的標(biāo)識(shí)符對(duì)于其所在塊來說是本地的,對(duì)于子塊來說是全局的。如果全局標(biāo)識(shí)符在子塊中被重新聲明,那么,全局和本地聲明的標(biāo)識(shí)符在子塊的作用域都是存在的,但是,只有本地標(biāo)識(shí)符是可見的,這時(shí)如果想引用全局標(biāo)識(shí)符,就需要添加限定修飾詞。

          雖然我們不能在同一塊中兩次聲明同一標(biāo)識(shí)符,但可以在兩個(gè)不同的塊中聲明同一標(biāo)識(shí)符。這兩個(gè)標(biāo)識(shí)符是互相獨(dú)立的,對(duì)其中任何一個(gè)的改變都不會(huì)影響到另一個(gè)。但是,一個(gè)塊不能引用同一級(jí)別中另外一個(gè)塊中的變量,因?yàn)閷?duì)于它來說,同級(jí)塊中標(biāo)識(shí)符即不是本地的,又不是全局的。

          下面的例子演示了作用域規(guī)則:

          DECLARE
            a   CHAR ;
            b   REAL ;
          BEGIN
            -- identifiers available here: a (CHAR), b
            DECLARE
              a   INTEGER ;
              c   REAL ;
            BEGIN
              -- identifiers available here: a (INTEGER), b, c
            END ;

            DECLARE
              d   REAL ;
            BEGIN
              -- identifiers available here: a (CHAR), b, d
            END ;
            -- identifiers available here: a (CHAR), b
          END ; 

          如果子塊中重新聲明了全局標(biāo)識(shí)符,本地標(biāo)識(shí)符優(yōu)先權(quán)高于全局標(biāo)識(shí)符,我們就不能再引用全局標(biāo)識(shí)符,除非使用限定名(qualified name)。修飾詞可以是封閉塊的標(biāo)簽,如下例所示:

          <<outer>>
          DECLARE
            birtddate   DATE ;
          BEGIN
            DECLARE
              birtddate   DATE ;
            BEGIN
             ...
              IF  birtddate = OUTER.birtddate tdEN
                ...
              END  IF ;
              ...
            END ;
            ...
          END ; 

          如下例所示,限定修飾詞也可以是封閉子程序的名稱:

          PROCEDURE  check_credit(...) IS
            rating   NUMBER ;

            FUNCTION  valid(...)
              RETURN  BOOLEAN  IS
              rating   NUMBER ;
            BEGIN
              ...
              IF  check_credit.rating < 3 tdEN  ...
            END ;
          BEGIN
            ...
          END ; 

          但是,在同一作用域內(nèi),標(biāo)簽和子程序不能使用相同的命名。

          六、變量賦值

          變量和常量都是在程序進(jìn)入塊或子程序的時(shí)候被初始化的。默認(rèn)情況下,變量都是被初始化成NULL的。除非我們?yōu)樽兞恐付ㄒ粋€(gè)值,否則結(jié)果是未知的。請(qǐng)看下面的例子:

          DECLARE
            count INTEGER ;
          BEGIN
            -- COUNT began witd a value of NULL .
            -- tdus tde expression ’COUNT + 1’ is also null.
            -- So after tdis assignment, COUNT is still NULL .
            count := count + 1; 

          為了避免這樣的情況,就要保證在賦值之前不要使用這個(gè)變量。

          我們可以使用表達(dá)式來為變量賦值,例如下面的語句為變量bonus賦值:

          bonus := salary * 0.15; 

          這里,我們需要保證的是salary * 0.15計(jì)算結(jié)果的類型必須和bonus類型保持一致。

          1、布爾型(Boolean)賦值

          只有TRUE、FALSE和NULL才可以賦給布爾類型的變量。例如:

          BEGIN
            done := FALSE ;
            WHILE  NOT  done LOOP
              ...
            END  LOOP ; 

          當(dāng)表達(dá)式中使用關(guān)系操作符的時(shí)候,返回結(jié)果也是布爾類型的值,所以下面的語句也是允許的。

          done := (count > 500); 

          2、利用SQL查詢?yōu)镻L/SQL變量賦值

          我們可以使用SELECT語句讓Oracle為變量賦值。對(duì)于查詢字段中的每一項(xiàng),在INTO子句的后面都必須有與之對(duì)應(yīng)的類型兼容的變量。看一下下面這個(gè)例子:

          DECLARE
            emp_id     emp.empno%TYPE ;
            emp_name   emp.ename%TYPE ;
            wages      NUMBER (7,2);
          BEGIN
            -- assign a value to emp_id here
            SELECT    ename, sal + comm INTO  emp_name, wages
              FROM    emp
             WHERE    empno = emp_id;
            ...
          END ; 

          但是,上面的用法不可以為布爾類型變量賦值。

          七、PL/SQL表達(dá)式與比較

          表達(dá)式由操作數(shù)和操作符構(gòu)成。一個(gè)操作數(shù)就是一個(gè)變量、常量、文字或是能夠返回一個(gè)值的函數(shù)。下面是一個(gè)簡(jiǎn)單的數(shù)學(xué)表達(dá)式:

          -X / 2 + 3 

          像負(fù)號(hào)(-)這樣的只作用于一個(gè)操作數(shù)的操作符稱為一元操作符;而像除號(hào)(/)這樣作用于兩個(gè)操作數(shù)的操作符稱為二元操作符。PL/SQL沒有三元操作符。

          最簡(jiǎn)單的表達(dá)式就是一個(gè)能直接算出值的變量。PL/SQL按照指定的操作符和操作數(shù)來計(jì)算表達(dá)式的值,結(jié)果值的數(shù)據(jù)類型是由表達(dá)式所在的關(guān)聯(lián)文決定的。

          由于操作符的運(yùn)算優(yōu)先級(jí)不同,表達(dá)式的計(jì)算順序也是不一樣的。下表是默認(rèn)的操作符優(yōu)先級(jí)順序。

          操作符 運(yùn)算
          ** 求冪
          +, - 正,負(fù)
          *, / 乘,除
          +, -, || 加,減,連接
          =, <, >, <=, >=, <>, !=, ~=, ^=,
          IS NULL, LIKE, BETWEEN, IN 比較
          NOT 邏輯非
          AND 與
          OR 或

          優(yōu)先級(jí)高的操作符會(huì)比優(yōu)先級(jí)低的操作符先求值。下例中,兩個(gè)表達(dá)式都能計(jì)算出結(jié)果8來,因?yàn)槌?hào)的優(yōu)先級(jí)要高于加號(hào)。優(yōu)先級(jí)相同的操作符不會(huì)采取特殊的計(jì)算順序。

          5 + 12 / 4

          12 / 4 + 5 

          我們可以使用括號(hào)控制計(jì)算順序。例如,下面的表達(dá)式值是7,而不是11,因?yàn)槔ㄌ?hào)覆蓋了默認(rèn)的操作符優(yōu)先順序:

          (8 + 6) / 2 

          再看一個(gè)例子。下面的運(yùn)算中,減法會(huì)在除法之前被計(jì)算,這是因?yàn)樽钌顚拥谋磉_(dá)式總是第一個(gè)被計(jì)算的:

          100 + (20 / 5 + (7 - 3)) 

          最后,我們看看如何使用括號(hào)來改善可讀性,即使不是在必須使用括號(hào)的時(shí)候:

          (salary * 0.05) + (commission * 0.25) 

          1、邏輯操作符

          邏輯操作符有AND、OR和NOT,其中AND和OR是二元操作符,而NOT是一元操作符。下面是對(duì)應(yīng)操作的真值表。

          x y x AND y x OR y NOT x
          TRUE TRUE TRUE TRUE FALSE
          TRUE FALSE FALSE TRUE FALSE
          TRUE NULL NULL TRUE FALSE
          FALSE TRUE FALSE TRUE TRUE
          FALSE FALSE FALSE FALSE TRUE
          FALSE NULL FALSE NULL TRUE
          NULL TRUE NULL TRUE NULL
          NULL FALSE FALSE NULL NULL
          NULL NULL NULL NULL NULL

          如上面的真值表所示,AND只在操作符兩邊的操作數(shù)都是真的情況才返回TRUE。另一方面,OR操作符兩邊的操作數(shù)只要有一個(gè)值為真就能返回TRUE。NOT會(huì)返回操作數(shù)相反的值。例如NOT TRUE返回FALSE。

          這里需要注意的地方是,由于NULL是一個(gè)不確定的值,所以NOT NULL的值也是無法確定的。

          運(yùn)算順序
          當(dāng)我們不用括號(hào)指定計(jì)算順序的時(shí)候,操作符的優(yōu)先級(jí)就會(huì)決定操作數(shù)的計(jì)算順序。比較下面兩個(gè)表達(dá)式:

          NOT  (valid AND  done)  NOT  valid AND  done 

          如果布爾變量valid和done的值都是FALSE,那么第一個(gè)表達(dá)式的結(jié)果就為TRUE。但是,第二個(gè)表達(dá)式的結(jié)果卻是FALSE,因?yàn)镹OT的優(yōu)先級(jí)要比AND高。因此,第二個(gè)表達(dá)式就等價(jià)于:

          (NOT  valid) AND  done 

          在下面的例子中,當(dāng)valid的值為FALSE,不論done值是多少,整個(gè)表達(dá)式的值總為FALSE:

          valid AND  done 

          同樣,當(dāng)下例中的valid的值為TRUE時(shí),不論done值是多少,整個(gè)表達(dá)式的值總為TRUE:

          valid OR  done 

          短路計(jì)算
          在計(jì)算邏輯表達(dá)式時(shí),PL/SQL使用的是短路計(jì)算方法。也就是說,PL/SQL在結(jié)果可以確定下來的時(shí)候,就不會(huì)再繼續(xù)計(jì)算表達(dá)式的值了。看一下下面這個(gè)例子:

          DECLARE
            ...
            on_hand    INTEGER ;
            on_order   INTEGER ;
          BEGIN
            ...
            IF  (on_hand = 0) OR  ((on_order / on_hand) < 5) tdEN
              ...
            END  IF ;
          END ; 

          當(dāng)on_hand的值是零的時(shí)候,操作符OR左面的操作數(shù)結(jié)果為TRUE,所以PL/SQL就不需要計(jì)算右邊的值了。如果PL/SQL是在應(yīng)用OR操作符之前計(jì)算兩個(gè)操作數(shù)的值的話,那么右邊的操作數(shù)就會(huì)產(chǎn)生一個(gè)除零的錯(cuò)誤。不管怎樣,依賴于"短路"計(jì)算不是一個(gè)好習(xí)慣。

          比較操作符
          比較操作符用于將一個(gè)表達(dá)式與另一個(gè)表達(dá)式進(jìn)行比較。結(jié)果是TRUE或FALSE或NULL。最常見的就是我們?cè)跅l件控制語句和SQL數(shù)據(jù)操作語句中的WHERE子句中使用比較操作符。例如:

          IF  quantity_on_hand > 0 tdEN
            UPDATE  inventory
               SET  quantity = quantity - 1
             WHERE  part_number = item_number;
          ELSE
            ...
          END  IF ; 

          關(guān)系操作符
          關(guān)系操作符可以讓我們隨意比較復(fù)雜的表達(dá)式。下面的表格列出了各種關(guān)系操作符的含義。

          操作符 含義
          =  等于
          <>, !=, ~=, ^=  不等于
          <  小于
          >  大于
          <=  小于等于
          >=  大于等于

          IS NULL 操作符
          如果IS NULL所作用的操作數(shù)為空,則返回結(jié)果TRUE,否則返回結(jié)果FALSE。與空值作比較,結(jié)果總是空。所以,無論什么時(shí)候跟空值作比較,都要使用IS NULL操作符:

          IF  variable IS  NULL  tdEN  ... 

          LIKE操作符
          我們可以使用LIKE操作符來判斷一個(gè)字符、字符串或CLOB類型的值是不是與我們指定的樣式相匹配。如果樣式匹配,LIKE就會(huì)返回TRUE,否則返回FALSE。用于LIKE匹配的樣式中,包含兩種通配符。下劃線(_):精確匹配一個(gè)字符;百分號(hào)(%):匹配零個(gè)或多個(gè)字符。如下面的例子中,如果ename的值是"JOHNSON",那么表達(dá)式結(jié)果就為TRUE:

          ename LIKE  'J%SON' 

          BETWEEN操作符
          BETWEEN操作符用于判斷目標(biāo)值是否在指定的目標(biāo)范圍內(nèi)。例如,下面表達(dá)式的結(jié)果就為FALSE:

          45 BETWEEN  38 AND  44 

          IN操作符
          IN操作符是用于測(cè)試目標(biāo)值是否是集合成員之一。其中,集合是可以包含NULL值的,但它們是被忽略的。例如,下面這個(gè)語句并不會(huì)刪除ename值為NULL的行:

          DELETE  FROM  emp
                WHERE  ename IN  (NULL , 'KING' , 'FORD' ); 

          此外,如果集合中包含了NULL值,下面表達(dá)式的運(yùn)算結(jié)果就是FALSE。

          value NOT  IN  set 

          所以,下面這個(gè)表達(dá)式也不會(huì)刪除任何行:

          DELETE  FROM  emp
                WHERE  ename NOT  IN  (NULL , 'king' ); 

          連接操作符
          雙豎線(||)可以當(dāng)作字符連接操作符,可以將兩個(gè)字符串(CHAR、VARCHAR2、CLOB或等價(jià)的Unicode支持的類型)連接起來。例如表達(dá)式

          'suit'  || 'case' 

          返回的結(jié)果就是

          'suitcase' 

          如果操作符兩邊的操作數(shù)都是CHAR類型,連接操作符返回的結(jié)果就是CHAR值。如果其中一個(gè)是CLOB值,操作符就返回臨時(shí)CLOB。其余情況均返回VARCHAR2類型。

          2、布爾表達(dá)式

          PL/SQL允許我們?cè)赟QL語句和過程語句中比較變量和常量。這樣的比較稱為布爾表達(dá)式,它們是由用關(guān)系操作符分割開的簡(jiǎn)單或復(fù)雜表達(dá)式組成。通常,布爾表達(dá)式是由邏輯操作符AND、OR或NOT連接。布爾表達(dá)式的運(yùn)算結(jié)果總是TRUE、FALSE或NULL。

          在SQL語句中,布爾表達(dá)式能讓我們指定一個(gè)表中哪些行記錄可以被影響。在過程語句中,布爾表達(dá)式是條件控制的基礎(chǔ)。其中有三種布爾表達(dá)式:算術(shù)、字符和日期。

          布爾算術(shù)表達(dá)式
          我們可以使用關(guān)系表達(dá)式來比較兩個(gè)數(shù)字等或不等。例如,下面的表達(dá)式結(jié)果就為真:

          number1    := 75;
          number2    := 70;

          number1 > number2   -- TRUE 

          布爾字符表達(dá)式
          我們也可以比較字符的等或不等。默認(rèn)情況下,比較都是基于字符串中每個(gè)字節(jié)的二進(jìn)制值的。比如,下面例子中的表達(dá)式結(jié)果就為真:

          string1    := 'Katdy' ;
          string2    := 'Katdleen' ;

          string1 > string2   -- TRUE 

          設(shè)置初始化參數(shù)NLS_COMP=ANSI,就能使用初始化參數(shù)NLS_SORT指定的整理序列(collating sequence)來進(jìn)行比較。整理序列是一個(gè)字符集中表現(xiàn)字符的數(shù)字代碼(numeric code)的內(nèi)部順序,如果一個(gè)字符的數(shù)字代碼比另一個(gè)大,那這個(gè)字符就比另一個(gè)字符大。關(guān)于字符在整理序列中出現(xiàn)的位置,每種語言都可能有不同的定義規(guī)則。比如說,重音字母可能會(huì)因數(shù)據(jù)庫(kù)的字符集的不同而排序不同,即使每一種情況下的二進(jìn)制值都相同。

          布爾日期表達(dá)式
          對(duì)于日期類型的比較,是按照年代的順序的。如下例,date1的值是大于date2的值的。

          date1    := '01-JAN-91' ;
          date2    := '31-DEC-90' ;

          date1 > date2   -- TRUE 

          關(guān)于PL/SQL的布爾表達(dá)式使用的一些建議
          一般地,不要把實(shí)型數(shù)字用于精確比較。實(shí)型數(shù)字一般都是按近似值存儲(chǔ)的。所以,下面的表式式值并不等于TRUE:

          COUNT    := 1;

          IF  COUNT = 1.0 tdEN
            ...
          END  IF ; 

          在作比較時(shí)使用括號(hào)是一個(gè)好習(xí)慣。例如,下面的這樣的表達(dá)式形式是不允許的,因?yàn)?100 < tax 的結(jié)果是布爾型,而布爾型是不能和數(shù)字500進(jìn)行比較的。

          100 < tax < 500   -- not allowed 

          解決方法是使用下面這樣的表達(dá)式:

          (100 < tax) AND  (tax < 500) 

          對(duì)于布爾型的變量來說,它的值要么為TRUE要么為FALSE,因此,對(duì)布爾型變量應(yīng)用比較操作是多余的。對(duì)于下面的內(nèi)容:

          WHILE  NOT (done = TRUE ) LOOP
            ...
          END  LOOP ; 

          可以簡(jiǎn)化為:

          WHILE  NOT  done LOOP
            ...
          END  LOOP ; 

          對(duì)COLB類型應(yīng)用比較操作符或是用LIKE和BETWEEN這樣的函數(shù)時(shí),可能會(huì)產(chǎn)生臨時(shí)LOB。我們就得確保有足夠大的表空間來容納這些臨時(shí)LOB。

          3、CASE表達(dá)式

          一個(gè)CASE表達(dá)式從一個(gè)或多個(gè)供選方案中選擇一個(gè)返回結(jié)果。CASE表達(dá)式使用一個(gè)選擇器來決定返回哪一個(gè)分支的結(jié)果。具體的語法形式如下:

          CASE  selector
            WHEN  expression1 tdEN  result1
            WHEN  expression2 tdEN  result2
            ...
            WHEN  expressionn tdEN  resultn
            [ELSE  resultN+1]
          END ; 

          選擇器后面跟著一個(gè)或多個(gè)WHEN子句,它們會(huì)被依次驗(yàn)證的。一旦有一個(gè)WHEN子句滿足條件的話,剩下的分支條件就不再執(zhí)行了。例如:

          DECLARE
            grade       CHAR (1)      := 'B' ;
            appraisal   VARCHAR2 (20);
          BEGIN
            appraisal    := CASE  grade
                             WHEN  'A'  tdEN  'Excellent'
                             WHEN  'B'  tdEN  'Very Good'
                             WHEN  'C'  tdEN  'Good'
                             WHEN  'D'  tdEN  'Fair'
                             WHEN  'F'  tdEN  'Poor'
                             ELSE  'No such grade'
                           END ;
          END ; 

          其中,ELSE子句是可選的,工作方式同IF語句中的ELSE子句相似。如果我們不提供ELSE子句,并且選擇器沒有匹配任何WHEN子句,表達(dá)式的返回的結(jié)果就是NULL。

          這種形式的CASE表達(dá)式的另外一種使用方法就是CASE語句,其中每個(gè)WHEN子句都可以是一個(gè)完整的PL/SQL塊。

          搜索式CASE表達(dá)式
          PL/SQL也提供了搜索式的CASE表達(dá)式,它的語法形式如下:

          CASE
            WHEN  expression1 tdEN  result1
            WHEN  expression2 tdEN  result2
            ...
            WHEN  expressionn tdEN  resultn
            [ELSE  resultN+1]
          END ; 

          搜索式CASE表達(dá)式?jīng)]有選擇器。每個(gè)WHEN子句包含一個(gè)能返回布爾值的搜索條件。例子如下:

          DECLARE
            grade       CHAR (1);
            appraisal   VARCHAR2 (20);
          BEGIN
            ...
            appraisal    := CASE
                             WHEN  grade = 'A'  tdEN  'Excellent'
                             WHEN  grade = 'B'  tdEN  'Very Good'
                             WHEN  grade = 'C'  tdEN  'Good'
                             WHEN  grade = 'D'  tdEN  'Fair'
                             WHEN  grade = 'F'  tdEN  'Poor'
                             ELSE  'No such grade'
                           END ;
            ...
          END ; 

          搜索條件按順序計(jì)算。搜索條件的布爾值決定了哪個(gè)WHEN子句被執(zhí)行。如果搜索條件的值為TRUE,它對(duì)應(yīng)的WHEN子句就會(huì)被執(zhí)行。只要其中一個(gè) WHEN子句被執(zhí)行,后續(xù)的搜索條件就不會(huì)被計(jì)算了。如果沒有匹配的條件,可選的ELSE就會(huì)被執(zhí)行。如果沒有匹配的WHEN子句,也沒有ELSE子句,表達(dá)式的結(jié)果就為NULL。

          4、在比較和條件語句中處理NULL值

          在使用NULL值時(shí),我們一定要記住下面幾條規(guī)則,避免發(fā)生一些常見的錯(cuò)誤:

          比較中如果有空值的話,那么計(jì)算結(jié)果總為NULL
          對(duì)空值應(yīng)用邏輯操作符NOT,結(jié)果還是NULL
          條件控制語句中,如果條件的運(yùn)算結(jié)果值為NULL的話,與之相關(guān)的語句就不會(huì)被執(zhí)行
          簡(jiǎn)單CASE語句中對(duì)于空值的判斷要使用WHEN expression IS NULL
          下例中,我們期待的是sequence_of_statements被執(zhí)行,因?yàn)閤和y看起來就是不等的。但是,由于NULL是不確定的值,那么,x是否等于y也就無法確定了。所以,sequence_of_statements并不會(huì)執(zhí)行。

          x    := 5;
          y    := NULL ;
          ...
          IF  x != y tdEN    -- yields NULL, not TRUE
            sequence_of_statements; -- not executed
          END  IF ; 

          同樣,下例中的sequence_of_statements也不會(huì)被執(zhí)行:

          a    := NULL ;
          b    := NULL ;
          ...
          IF  a = b tdEN    -- yields NULL, not TRUE
            sequence_of_statements; -- not executed
          END  IF ; 

          NOT操作符
          讓我們?cè)倩貞浺幌逻壿嫴僮鞣鸑OT,當(dāng)對(duì)一個(gè)NULL值應(yīng)用NOT時(shí),結(jié)果總是NULL。因此,下面兩段內(nèi)容并不相同。

          IF  x > y tdEN
            high    := x;
          ELSE
            high    := y;
          END  IF ;  IF  NOT  x > y tdEN
            high    := y;
          ELSE
            high    := x;
          END  IF ; 

          當(dāng)IF條件值為FALSE或NULL時(shí),ELSE部分就會(huì)被執(zhí)行。如果x和y都不為NULL的話,兩段程序運(yùn)行的效果是一樣的。但是,如果IF條件為NULL的話,第一段是給y賦值,而第二段是給x賦值。

          零長(zhǎng)度字符串
          PL/SQL把零長(zhǎng)度字符串當(dāng)作空值處理,這其中包括由字符函數(shù)和布爾表達(dá)式返回的值。下面的語句均是給目標(biāo)變量賦空值的操作:

          null_string    := TO_CHAR('');
          zip_code       := SUBSTR(address, 25, 0);
          valid          :=(NAME != ''); 

          所以,對(duì)于檢測(cè)空字符串,要使用IS NULL操作符:

          IF  my_string IS  NULL  tdEN  ... 

          連接操作符
          連接操作符會(huì)忽略空值,例如表達(dá)式

          'apple'  || NULL  || NULL  || 'sauce' 

          會(huì)返回

          'applesauce' 

          函數(shù)
          如果給內(nèi)置函數(shù)傳遞空值,一般也都會(huì)返回空值,但以下幾種情況除外。

          函數(shù)DECODE將它的第一個(gè)參數(shù)和后面的一個(gè)或多個(gè)表達(dá)式相比較(表達(dá)式的值有可能為空),如果比較的內(nèi)容相匹配,就會(huì)返回后面的結(jié)果表達(dá)式。例如在下面的例子中,如果字段rating的值為空,DECODE就會(huì)返回1000:

          SELECT  DECODE(rating,
                        NULL , 1000,
                        'C' , 2000,
                        'B' , 4000,
                        'A' , 5000
                       )
            INTO  credit_limit
            FROM  accts
           WHERE  acctno = my_acctno; 

          函數(shù)NVL在判斷出第一個(gè)參數(shù)是空的情況下,會(huì)返回第二個(gè)參數(shù)的值,否則直接返回第一個(gè)參數(shù)的值。使用方法如下:

          start_date := NVL(hire_date, SYSDATE ); 

          函數(shù)REPLACE第二個(gè)參數(shù)是NULL的時(shí)候,它就會(huì)返回第一個(gè)參數(shù)的值,不管是否有第三個(gè)參數(shù)。例如,在下面例子中,結(jié)果字符串new_string的值和old_string的值完全一樣。

          new_string := REPLACE(old_string, NULL , my_string); 

          如果第三個(gè)參數(shù)為空的話,REPLACE就會(huì)把第一個(gè)參數(shù)中出現(xiàn)的第二個(gè)參數(shù)刪除,然后返回結(jié)果。如下面這個(gè)例子:

            syllabified_name    := 'gold - i - locks' ;
            NAME                := REPLACE(syllabified_name,
                                           ' - ' ,
                                           NULL
                                          ); 

          運(yùn)算的結(jié)果字符串是"goldilocks"。如果第二個(gè)和第三個(gè)參數(shù)都是NULL值,REPLACE就直接返回第一個(gè)參數(shù)。

          八、內(nèi)置函數(shù)

          PL/SQL為我們提供了許多功能強(qiáng)大的數(shù)據(jù)操作函數(shù)。這些函數(shù)可以分為以下幾類:

          錯(cuò)誤報(bào)告
          數(shù)字
          字符
          類型轉(zhuǎn)換
          日期
          對(duì)象引用
          雜項(xiàng)
          下面的表格是各個(gè)分類的函數(shù)。

          錯(cuò)誤  數(shù)字  字符  轉(zhuǎn)換  日期  對(duì)象引用  雜項(xiàng)
          SQLCODE ABS ASCII CHARTOROWID ADD_MONtdS DEREF BFILENAME
          SQLERRM ACOS CHR CONVERT CURRENT_DATE REF DECODE
            ASIN CONCAT HEXTORAW CURRENT_TIMESTAMP VALUE DUMP
            ATAN INITCAP RAWTOHEX DBTIMEZONE TREAT EMPTY_BLOB
            ATAN2 INSTR ROWIDTOCHAR EXTRACT   EMPTY_CLOB
            BITAND INSTRB TO_BLOB FROM_TZ   GREATEST
            CEIL LENGtd TO_CHAR LAST_DAY   LEAST
            COS LENGtdB TO_CLOB LOCALTIMESTAMP   NLS_CHARSET_DECL_LEN
            COSH LOWER TO_DATE MONtdS_BETWEEN   NLS_CHARSET_ID
            EXP LPAD TO_MULTI_BYTE NEW_TIME   NLS_CHARSET_NAME
            FLOOR LTRIM TO_NCLOB NEXT_DAY   NVL
            LN NLS_INITCAP TO_NUMBER NUMTODSINTERVAL   SYS_CONTEXT
            LOG NLS_LOWER TO_SINGLE_BYTE NUMTOYMINTERVAL   SYS_GUID
            MOD NLSSORT   ROUND   UID
            POWER NLS_UPPER   SESSIONTIMEZONE   USER
            ROUND REPLACE   SYSDATE   USERENV
            SIGN RPAD   SYSTIMESTAMP   VSIZE
            SIN RTRIM   TO_DSINTERVAL    
            SINH SOUNDEX   TO_TIMESTAMP    
            SQRT SUBSTR   TO_TIMESTAMP_LTZ    
            TAN SUBSTRB   TO_TIMESTAMP_TZ    
            TANH TRANSLATE   TO_YMINTERVAL    
            TRUNC TRIM   TZ_OFFSET    
              UPPER   TRUNC    

          除了錯(cuò)誤報(bào)告(error-reporting)函數(shù)SQLCODE和SQLERRM之外,我們可以在SQL語句中使用上面所有的函數(shù)。同樣,tbw淘寶商城我們可以在過程表達(dá)式中使用除了對(duì)象引用函數(shù)DEFREF、REF、VALUE和雜函數(shù)(miscellaneous function)DECODE、DUMP、VSIZE之外的所有函數(shù)。

          雖然SQL聚合函數(shù)(aggregate function,如AVG和COUNT)和SQL解析函數(shù)(analytic function,如CORR和LAG)沒有組合到PL/SQL中,但我們?nèi)钥梢栽赟QL語句中使用它們(但不能在過程語句中使用)。

           

          posted on 2012-06-01 12:07 chen11-1 閱讀(30862) 評(píng)論(0)  編輯  收藏 所屬分類: oracle


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           

          My Links

          Blog Stats

          常用鏈接

          留言簿(4)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          新聞檔案

          tbw淘寶商城-首頁

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 临江市| 仁布县| 高唐县| 巴马| 浪卡子县| 迁安市| 确山县| 探索| 泽普县| 和硕县| 东城区| 梅河口市| 武穴市| 略阳县| 水富县| 湟中县| 南和县| 白山市| 油尖旺区| 兰溪市| 神池县| 湟中县| 衡东县| 文成县| 维西| 雷波县| 扬州市| 龙胜| 吉安市| 星座| 光山县| 元氏县| 凯里市| 四子王旗| 定襄县| 烟台市| 荥经县| 鄯善县| 正蓝旗| 永福县| 边坝县|