PLSQL循序漸進全面學習教程

 

課程 一 PL/SQL 基本查詢與排序

本課重點:
   1、寫SELECT語句進行數據庫查詢
   2、進行數學運算
   3、處理空值
   4、使用別名ALIASES
   5、連接列
   6、在SQL PLUS中編輯緩衝,修改SQL SCRIPTS
   7、ORDER BY進行排序輸出。
   8、使用WHERE 字段。

一、寫SQL 命令:
     不區分大小寫。
     SQL 語句用數字分行,在SQL PLUS中被稱爲緩衝區。
     最後以;或 / 結束語句。
     也可以用RUN來執行語句

二、例1:
    SQL> SELECT dept_id, last_name, manager_id
    2 FROM s_emp;

    SQL> SELECT last_name, salary * 12, commission_pct
    2 FROM s_emp;

對於數值或日期型的字段,可以進行相應的四則運算,優先級與標準的高級語言相同。

    SQL> SELECT last_name, salary, 12 * (salary + 100)
    2 FROM s_emp;

三、列的別名ALIASES:
    計算的時候特別有用;
    緊跟着列名,或在列名與別名之間加“AS”;
    如果別名中含有SPACE,特殊字符,或大小寫,要用雙引號引起。
    例(因字體原因,讀者請記住:引號爲英文雙引號Double Quotation):

    SQL> SELECT last_name, salary,
    2 12 * (salary + 100) ”Annual Salary”
    3 FROM s_emp;

四、連接符號:||
    連接不同的列或連接字符串
    使結果成爲一個有意義的短語:
   
    SQL> SELECT first_name || ’ ’ || last_name
    2 || ’, ’|| title ”Employees”
    3 FROM s_emp;

五、管理NULL值:

    SQL> SELECT last_name, title,
    2 salary * NVL(commission_pct,0)/100 COMM
    3 FROM s_emp;

此函數使NULL轉化爲有意義的一個值,相當於替換NULL。

六、SQL PLUS的基本內容,請參考<SQL PLUS 簡單實用精髓篇 >

七、ORDER BY 操作:
與其他SQL92標準數據庫相似,排序如:SELECT expr FROM table [ORDER BY [ASC|DESC]];
從Oracle7 release 7.0.16開始,ORDER BY 可以用別名。
另:通過位置判斷排序:
    SQL> SELECT last_name, salary*12
    2 FROM s_emp
    3 ORDER BY 2;

這樣就避免了再寫一次很長的表達式。

另:多列排序:
    SQL> SELECT last name, dept_id, salary
    2 FROM s_emp
    3 ORDER BY dept_id, salary DESC;

八、限制選取行:
SELECT expr FROM table [WHERE condition(s)] [ORDER BY expr];

例1:
    SQL> SELECT first_name, last_name, start_date
    2 FROM s_emp
    3 WHERE start_date BETWEEN ’09-may-91’
    4 AND ’17-jun-91’;

例2:
    SQL> SELECT last_name
    2 FROM s_emp
    3 WHERE last_name LIKE ’_a%’; //顯示所有第二個字母爲 a的last_name

例3:如果有列爲NULL
    SQL> SELECT id, name, credit_rating
    2 FROM s_customer
    3 WHERE sales_rep_id IS NULL;

優先級:
Order        Evaluated Operator
1   All comparison operators (=, <>, >, >=, <, <=, IN, LIKE, IS NULL, BETWEEN)
2   AND
3   OR

總結:我們今天主要學習瞭如何進行查詢SELECT操作,具體的組合查詢與子查詢將在以後的課堂中學習,同時希望大家可以工作、學習中多多摸索,實踐!


課程 二 PL/SQL 查詢行函數

本課重點:
   1、掌握各種在PL/SQL中可用的ROW函數
   2、使用這些函數的基本概念
   3、SELECT語句中使用函數
   4、使用轉換函數

一、FUNCTION的作用:
進行數據計算,修改獨立的數據,處理一組記錄的輸出,不同日期顯示格式,進行數據類型轉換
函數分爲:單獨函數(ROW)和分組函數
注意:可以嵌套、可以在SELECT, WHERE, 和 ORDER BY中出現。
語法:function_name (column|expression, [arg1, arg2,...])

二、字符型函數
    1、LOWER 轉小寫
    2、UPPER
    3、INITCAP 首字母大寫
    4、CONCAT 連接字符,相當於 ||
    5、SUBSTR SUBSTR(column|expression,m[,n])
    6、LENGTH   返回字符串的長度
    7、NVL    轉換空值

    其中,1、2經常用來排雜,也就是排除插入值的大小寫混用的干擾,如:

    SQL> SELECT first_name, last_name
    2 FROM s_emp
    3 WHERE UPPER(last_name) = ’PATEL’;
   
    FIRST_NAME LAST_NAME
    -------------------- --------------------
    Vikram    Patel
    Radha     Patel

三、數學運算函數

1、ROUND  四捨五入
  ROUND(45.923,2) = 45.92
  ROUND(45.923,0) = 46
  ROUND(45.923,-1) = 50

2、TRUNC  截取函數
  TRUNC(45.923,2)= 45.92
  TRUNC(45.923)= 45
  TRUNC(45.923,-1)= 40

3、MOD 餘除
  MOD(1600,300)

實例:

SQL> SELECT ROUND(45.923,2), ROUND(45.923,0),
2 ROUND(45.923,-1)
3 FROM SYS.DUAL;

四、ORACLE 日期格式和日期型函數:
1、默認格式爲DD-MON-YY.
2、SYSDATE是一個求系統時間的函數
3、DUAL['dju:el] 是一個僞表,有人稱之爲空表,但不確切。

    SQL> SELECT SYSDATE
    2 FROM SYS.DUAL;

4、日期中應用的算術運算符
例:
    SQL> SELECT last_name, (SYSDATE-start_date)/7 WEEKS
    2 FROM s_emp
    3 WHERE dept_id = 43;
   
DATE+ NUMBER = DATE
DATE-DATE= NUMBER OF DAYS
DATE + (NUMBER/24) = 加1小時

5、函數:
MONTHS_BETWEEN(date1, date2) 月份間隔,可正,可負,也可是小數
ADD_MONTHS(date,n) 加上N個月,這是一個整數,但可以爲負
NEXT_DAY(date,‘char’) 如:NEXT_DAY (restock_date,’FRIDAY’),從此日起下個週五。
ROUND(date[,‘fmt’])
TRUNC(date[,‘fmt’])

解釋下面的例子:
    SQL> SELECT id, start_date,
    2 MONTHS_BETWEEN (SYSDATE,start_date) TENURE,
    3 ADD_MONTHS(start_date,6) REVIEW
    4 FROM s_emp
    5 WHERE MONTHS_BETWEEN (SYSDATE,start_date)<48;

我們看到:
    MONTHS_BETWEEN (SYSDATE,start_date)<48,說明至今工作未滿一年的員工。
    LAST_DAY (restock_date) 返回本月的最後一天

    SQL> select round(sysdate,'MONTH') from dual
   
    ROUND(SYSD
    ----------
    01-11月-01

round(sysdate,'YEAR') = 01-1月 -02  

    ROUND 之後的值比基值大的最小符合值,大家可以用更改系統時間的方法測試,以15天爲分界線,也是非常形象的四捨五入,而TRUNC恰好相反,是對現有的日期的截取。

五、轉換函數:
1、TO_CHAR    使一個數字或日期轉換爲CHAR
2、TO_NUMBER  把字符轉換爲NUMBER
3、TO_DATE    字符轉換爲日期

這幾個函數較爲簡單,但要多多實踐,多看複雜的實例。

    SQL> SELECT ID,TO_CHAR(date_ordered,’MM/YY’) ORDERED
    2 FROM s_ord
    3 WHERE sales_rep_id = 11;

轉換時,要注意正確的缺省格式:
    SELECT TO_DATE('03-MAR-92') CORRECT FROM DUAL;//正確
    SELECT TO_DATE('031092') CORRECT FROM DUAL;//不正確
    SELECT TO_DATE('031095','MMDDYY') ERRORR FROM DUAL  // 輸出 3月10日
    SELECT TO_DATE('031095','DDMMYY') ERRORR FROM DUAL  // 輸出 10月3日

4、實例:
    select to_char(sysdate,'fmDDSPTH "of" MONTH YYYY AM') TODAYS FROM DUAL;
   
    TODAYS
    --------------------------------
    SIXTEENTH of 11月 2001 下午

大小寫沒有什麼影響,引號中間的是不參與運算。

實例 :
    SELECT ROUND(SALARY*1.25) FROM ONE_TABLE;

    意義:漲25%工資後,去除小數位。在現實操作中,很有意義。

5、混合實例:
    SQL> SELECT last_name, TO_CHAR(start_date,
    2 ’fmDD ”of” Month YYYY’) HIREDATE
    3 FROM s_emp
    4 WHERE start_date LIKE ’%91’;
   
    LAST_NAME HIREDATE   
    ------------ --------------------
    Nagayama 17 of June 1991
    Urguhart 18 of January 1991
    Havel 27 of February 1991

這裏要注意:fmDD 和 fmDDSPTH之間的區別。

    SQL> SELECT id, total, date_ordered
    2 FROM s_ord
    3 WHERE date_ordered =
    4 TO_DATE(’September 7, 1992’,’Month dd, YYYY’);

六、獨立的函數嵌套
    SQL> SELECT CONCAT(UPPER(last_name),
    2 SUBSTR(title,3)) ”Vice Presidents”
    3 FROM s_emp
    4 WHERE title LIKE ’VP%’;

* 嵌套可以進行到任意深度,從內向外計算。

例:
    SQL> SELECT TO_CHAR(NEXT_DAY(ADD_MONTHS
    2 (date_ordered,6),’FRIDAY’),
    3 ’fmDay, Month ddth, YYYY’)
    4 ”New 6 Month Review”
    5 FROM s_ord
    6 ORDER BY date_ordered;
   
    SQL> SELECT last_name,
    2 NVL(TO_CHAR(manager_id),’No Manager’)
    3 FROM s_emp
    4 WHERE manager_id IS NULL;

    對於例子,大家重要的理解,並多做測試,並注意英文版和中文版在日期上的區別。
    有些教材上的例子,不要盲目的相信其結果,實踐後纔有發言權,希望大家能夠在學習的過程中不要忽略了用,多想一想爲什麼實例要如此設計,在何種情況下應用此實例來解決問題。這樣,我們才真正掌握了知識。
   

課程 三 從多個表中提取數據
                                                                     
本課重點:
 1、SELECT FROM 多個表,使用等連接或非等連接
 2、使用外連接OUTER JOIN
 3、使用自連接

一、連接的概念:
是指一個從多個表中的數據進行的查詢。連接一般使用表的主鍵和外鍵。
連接類型:等連接、不等連接、外連接、自連接

二、Cartesian product(笛卡兒集)
指的是當JOIN條件被省略或無效時,所有表的行(交叉)都被SELECT出來的現象。
Cartesian product可以產生大量的記錄,除非是你有意如此,否則應該加上某種條件限制。

 SQL> SELECT name, last_name
 2 FROM s_dept, s_emp;
 300 rows selected.

其中一個表12行,一個表25行。

三、簡單連接查詢:
語法結構:SELECT table.column, table.column...
   FROM table1, table2
   WHERE table1.column1 = table2.column2;
如:
 SQL> SELECT s_emp.last_name, s_emp.dept_id,
 2 s_dept.name
 3 FROM s_emp, s_dept
 4 WHERE s_emp.dept_id = s_dept.id;

*注意:表前綴的重要性:

 SQL> SELECT s_dept.id ”Department ID”,
 2 s_region.id ”Region ID”,
 3 s_region.name ”Region Name”
 4 FROM s_dept, s_region
 5 WHERE s_dept.region_id = s_region.id;

在WHERE 段中,如果沒有前綴,兩個表中都有ID字段,就顯得的模棱兩可,AMBIGUOUS。
這在實際中應該儘量避免。
WHERE 字段中,還可以有其他的連接條件,如在上例中,加上:
INITCAP(s_dept.last_name) = ’Menchu’;
再如:WHERE s_emp.dept_id = s_dept.id AND s_dept.region_id = s_region.id AND s_emp.commission_pct > 0;

四、表別名ALIAS:
1、使用別名進行多表查詢 。
2、僅在這個查詢中生效,一旦用了表別名,就不能再用表的原有的名字進行連接。
實例:
 SQL> SELECT c.name ”Customer Name”,
 2 c.region_id ”Region ID”,
 3 r.name ”Region Name”
 4 FROM s_customer c, s_region r
 5 WHERE c.region_id = r.id;

別名最多可以30個字符,但當然越少越好。最好也能容易識別。

五、非等連接
非等連接一般用在沒有明確的等量關係的兩個表;
最簡單的說:非等連接就是在連接中沒有“=”出現的連接。

 SQL> SELECT e.ename, e.job, e.sal, s.grade
 2 FROM emp e, salgrade s
 3 WHERE e.sal BETWEEN s.losal AND s.hisal;

*說明:Create a non-equijoin to evaluate an employee’s salary grade. The salary 必須在另一個表中最高和最低之間。
其他操作符<= >= 也可以實現,但是BETWEEN是非常簡單實用的。
BETWEEN ....AND是指閉區間的,這點要注意 ,請大家測試。

六、外連接
語法結構:SELECT table.column, table.column
   FROM table1, table2
   WHERE table1.column = table2.column(+);
實例:
 SQL> SELECT e.last_name, e.id, c.name
 2 FROM s_emp e, s_customer c
 3 WHERE e.id (+) = c.sales_rep_id
 4 ORDER BY e.id;

顯示.....,即使有的客戶沒有銷售代表。
* 可以理解爲有+號的一邊出現了NULL,也可以做爲合法的條件。
外連接的限制:
1、外連接符只能出現在信息缺少的那邊。
2、在條件中,不能用 IN 或者 OR做連接符。

七、自連接
同一個表中使用連接符進行查詢;
FROM 的後面用同一個表的兩個別名。
實例:
 SQL> SELECT worker.last_name||’ works for ’||
 2 manager.last_name
 3 FROM s_emp worker, s_emp manager
 4 WHERE worker.manager_id = manager.id;
 
意味着:一個員工的經理ID匹配了經理的員工號,但這個像繞口令的連接方式並不常用。
以後我們會見到一種 子查詢:
select last_name from s_emp where salary=(select max(salary) from s_emp)
也可以看作是一種變向的自連接,但通常我們將其歸類爲子查詢。


課程 四 組函數

本課重點:
   1、瞭解可用的組函數
   2、說明每個組函數的使用方法
   3、使用GROUP BY
   4、通過HAVING來限制返回組

一、概念:
      組函數是指按每組返回結果的函數。
      組函數可以出現在SELECT和HAVING 字段中。
      GROUP BY把SELECT 的結果集分成幾個小組。
      HAVING 來限制返回組,對RESULT SET而言。
     
二、組函數:(#號的函數不做重點)
  1、AVG
  2、COUNT
  3、MAX
  4、MIN
  5、STDDEV #
  6、SUM
  7、VARIANCE #
語法:
   SELECT column, group_function
      FROM table
     [WHERE condition]
      [GROUP BY group_by_expression]
       [HAVING group_condition]
         [ORDER BY column];
實例1:
 SQL> SELECT AVG(salary), MAX(salary), MIN(salary),
 2 SUM(salary)
 3 FROM s_emp
 4 WHERE UPPER(title) LIKE ’SALES%’;
 AVG(SALARY) MAX(SALARY) MIN(SALARY) SUM(SALARY)
 ----------- ----------- ----------- -----------
  1476       1525          1400        7380
 
*說明:很多函數,我們在講函數的已經向大家介紹過,但在此爲何叫分組函數呢,主要是因爲它們可以與GROUP BY來形成對不同組的計算,相當於在很多值中進行挑選。
* MIN MAX函數可以接任何數據類型。
如果是MIN(last_name), MAX(last_name),返回的是什麼呢?
千萬記住,不是指LAST_NAME的長度,而是指在FIRST字母的前後順序,第一個相同,然後比較第二個,如:xdopt > cssingkdkdk >   adopt > acccc

實例2:(返回所有非空行個數)

 SQL> SELECT COUNT(commission_pct)
 2 FROM s_emp
 3 WHERE dept_id = 31;

三、GROUP BY的應用:
先看一個簡單實例:

 SQL> SELECT credit_rating, COUNT(*) ”# Cust”
 2 FROM s_customer
 3 GROUP BY credit_rating;
 
*注意這裏別名的應用,複習一下從前的課程,加了引號後,就可以用特殊字符,但也僅有三個:#$_,什麼對象的名字都如此。當然空格也是可以的。
複雜實例:

 SQL> SELECT title, SUM(salary) PAYROLL
 2 FROM s_emp
 3 WHERE title NOT LIKE ’VP%’
 4 GROUP BY title
 5 ORDER BY SUM(salary);
 
這裏要注意一下幾個CLAUSE的先後次序。WHERE在這裏主要是做參與分組的記錄的限制。
**另外,如果要選取出來一個不加組函數的列,如上面的TITLE,就要把這個列GROUP BY !否則要出錯的!信息爲:
 ERROR at line 1:
 ORA-00937: not a single-group group function
 
理論很簡單,如果不GROUP BY TITLE,顯示哪一個呢?這個在試題中經常出現。
結論:不加分組函數修飾的列必定要出現在GROUP BY 裏。
錯誤實例:
 SQL> SELECT dept_id, AVG(salary)
 2 FROM s_emp
 3 WHERE AVG(salary) > 2000
 4 GROUP BY dept_id;
 5 WHERE AVG(salary) > 2000
 
 ERROR at line 3:
 ORA-00934: group function is not allowed here

應在GROUP BY 後面加上HAVING AVG(salary) > 2000;因爲是用來限制組的返回。

多級分組實例:
 SQL> SELECT dept_id, title, COUNT(*)
 2 FROM s_emp
 3 GROUP BY dept_id, title;

就是先按照DEPT_ID分組,當DEPT_ID相同的時候,再按TITLE分組,而COUNT(*)以合成的組計數。順序對結果有決定性的影響。
      
總結:本課我們主要學習了分組函數的使用及如何進行分組查詢,我們可以想像一下,SQL SERVER中有COMPUTE BY,來進行分組總數的計算,但在ORACLE中是沒有的。大家可以建立一個有多個列,多個重複值的表,然後進行各種分組的演示,用得多了,自然明瞭。
    

課程 五 子查詢

本課重點:
   1、在條件未知的情況下采用嵌套子查詢
   2、用子查詢做數據處理
   3、子查詢排序
  
一、概述:
子查詢是一種SELECT句式中的高級特性,就是一個SELECT語句作爲另一個語句的一個段。我們可以利用子查詢來在WHERE字段中引用另一個查詢來攻取值以補充其無法事先預知的子結果。子查詢可以用在WHERE子句,HAING子句,SELECT或DELETE語句中的FROM 子句。

*注意:
1、子查詢必須在一對圓括號裏。
2、比較符號:>, =, 或者 IN.
3、子查詢必須出現在操作符的右邊
4、子查詢不能出現在ORDER BY裏   (試題中有時出現找哪行出錯)
   
二、子查詢的執行過程:
NESTED QUERY                            MAIN QUERY
SQL> SELECT dept_id                     SQL> SELECT last_name, title
2 FROM s_emp                            2 FROM s_emp
3 WHERE UPPER(last_name)=’BIRI’;        3 WHERE dept_id =

這裏 ,每個查詢只運行一次。當然,子查詢要首先被執行,大家設想一下,如果子查詢中有一個以上的人的LASTNAME爲BIRI,會如何?-----會出錯,因爲不能用=來連接。
      ORA-1427: single-row subquery returns more than one row
以上的查詢也被稱之爲單行子查詢。
DELECT子查詢實例:
 delete from new_table
  where cata_time > to_date('19990901','yyyymmdd') and pro_name=(
   select pro_name from new_product where pro_addr in ('bj','sh'))

三、子查詢中的GROUP 函數的應用
實例 1:
 SQL> SELECT last_name, title, salary
 2 FROM s_emp
 3 WHERE salary <
 4 (SELECT AVG(salary)
 5 FROM s_emp);

實例2:選擇出工資最高的員工的家庭住址:
 select emp_addr from employees where salary =
  (select max(salary) from employees);

這是一個簡單實用的例子,可以衍生出很多情況,在實際應用經常出現,請大家多多思考。

實例3:
 SQL> SELECT dept_id, AVG(salary)
 2 FROM s_emp
 3 GROUP BY dept_id
 4 HAVING AVG(salary) >
 5 (SELECT AVG(salary)
 6 FROM s_emp
 7 WHERE dept_id = 32);

子查詢被多次執行,因爲它出現在HAVING 子句中。
 SQL> SELECT title, AVG(salary)
 2 FROM s_emp
 3 GROUP BY title
 4 HAVING AVG(salary) =
 5 (SELECT MIN(AVG(salary))
 6 FROM s_emp
 7 GROUP BY title);

對子查詢,我們瞭解這麼多在理論上已經覆蓋了所有的知識點,對於UPDATE 和DELETE的子查詢,不作爲重點,但也要練習掌握。今天到這,謝謝大家。
   

課程 六 運行時應用變量

本課重點:
   1、創建一個SELECT語句,提示USER在運行時先對變量賦值。
   2、自動定義一系列變量,在SELECT運行時進行提取。
   3、在SQL PLUS中用ACCEPT定義變量

一、概述:
變量可以在運行時應用,變量可以出現在WHERE 字段,文本串,列名,表名等。
1、我們這裏的運行時,指的是在SQL PLUS中運行。
2、ACCEPT :讀取用戶輸入的值並賦值給變量
3、DEFINE:創建並賦值給一個變量
4、在做REPORT時經常使用,比如對某個部門的銷售信息進行統計,部門名稱可以以變量代替。
SQL PLUS不支持對輸入數據的有效性檢查,因此提示要簡單且不模棱兩可。

二、應用實例:
1、
 SQL> SELECT id, last_name, salary
 2 FROM s_emp
 3 WHERE dept_id = &department_number;

2、可以在賦值前後進行比較:
 SET VERIFY ON 
 ..... 
 1* select * from emp where lastname='&last_name'

輸入 last_name 的值: adopt
原值  1: select * from emp where lastname='&last_name'
新值  1: select * from emp where lastname='adopt'

----如果在原語句中沒有單引號,那麼在輸入值的時候要手工加上單引號。一般字符和日期型要在語句中加上單引號。
SET VERIFY OFF 之後,原值和新值這兩句消失。這在ORACLE8I中是默認爲ON。

3、子句爲變量:WHERE &condition; 要注意引號

三、DEFINE和ACCEPT的應用:
1、
 SET ECHO OFF   //使內容不 顯示在用戶界面
 ACCEPT p_dname PROMPT ’Provide the department name: ’
 SELECT d.name, r.id, r.name ”REGION NAME”
  FROM s_dept d, s_region r
  WHERE d.region_id = r.id AND UPPER(d.name) LIKE UPPER(’%&p_dname%’)
 /
 SET ECHO ON

存爲文件:l7prompt.SQL

 SQL> START l7prompt
 Provide the department name: sales

2、
 SQL> DEFINE dname = sales
 SQL> DEFINE dname
 DEFINE dname = ”sales” (CHAR)
 SQL> SELECT name
 2 FROM s_dept
 3 WHERE lower(name) = ’&dname’;

可以正常執行了。
SQL> DEFINE dname 主要是顯示當前的變量是否賦值,值是什麼。當然,我們可以用UNDEFINEGO 來使變量恢復初始,不然它會一直保持下去。

3、如果變量在SQL SCRIPT文件中確定 :可以SQL> START l7param President 來賦值。

總結:本課主要針對較古老的SQLPLUS方法,在REPORT和結果集生成方面使用變量,達到方便操作,動態修改的目的。
 


課程 七   其他數據庫對象

SEQUENCE

創建實例:
 SQL> CREATE SEQUENCE s_dept_id
 2 INCREMENT BY 1
 3 START WITH 51
 4 MAXVALUE 9999999
 5 NOCACHE
 6 NOCYCLE;
 
 Sequence created.

1、NEXTVAL和CURRVAL的用法
只有在INSERT中,纔可以作爲子查詢出現。

以下幾個方面不可用子查詢:
    SELECT子句OF A VIEW
    有DISTINCT的出現的SELECT。
    有GROUP BY,HAVING,ORDER BY的SELECT 子句。
    SELECT 或DELETE,UPDATE 中的子查詢。
    DEFAULT選項中不能用。

2、編輯SEQUENCE
  只有OWNER或有ALTER權限的用戶才能修改SEQUENCE
  未來的NUMBER受修改的影響。
  不能修改START WITH,如果變,則要RE-CREATE。
  修改會受到某些有效性檢驗的限制,如MAXVALUE

3、刪除:
  DROP SEQUENCE sequence;

ORACLE對象之INDEX

一、INDEX概述:
 是ORACLE的一種數據對象,用POINTER來加速查詢行。通過快速路徑存取方法定位數據並減少I/O。 INDEX獨立於表。INDEX由ORACLE SERVER來使用和保持。

二、索引如何建立?
 1、自動:通過PRIMARY KEY和UNIQUE KEY約束來建立。
 2、用戶手工建立非唯一性索引。

三、創建方法:
語法:CREATE INDEX index ON table (column[, column]...);

何時建立INDEX:
    此列經常被放到WHERE字段或JOIN來作條件查詢。
    此列含有大量的數據。
    此列含有大量的空值。
    兩個或幾個列經常同時放到WHERE字段進行組合查詢
    表很大而且只有少於2-4% 的ROW可能被查詢的時候。
    以下情況不要建立索引:
    表很小;
    表被更新頻繁。

四、查看已經存在的索引:
 1、USER_INDEXES可以查詢索引名和類型。
 2、USER_IND_COLUMNS包含索引名、表名、列名。

實例:
    SQL> SELECT ic.index_name, ic.column_name,
    2 ic.column_position col_pos, ix.uniqueness
    3 FROM user_indexes ix, user_ind_columns ic
    4 WHERE ic.index_name = ix.index_name
    5 AND ic.table_name = ’S_EMP’;

五、刪除索引:
     DROP INDEX index;


SYNONYMS 同義詞

語法:CREATE [PUBLIC] SYNONYM synonym for object;

*注意:此對象不能包含在一個包裏;一個私有的同義詞不能與同一USER的其他對象重名。

    DROP SYNONYM D_SUM;


課程 八 用戶訪問控制
                                  
本課重點:
   1、創建用戶
   2、創建角色來進行安全設置
   3、使用GRANT或REVOKE 來控制權限
  
一、概述:
    ORACLE通過用戶名和密碼進行權限控制。
    數據庫安全:系統安全和數據安全
    系統權限:使用戶可以訪問數據庫
    對象權限:操縱數據庫中的對象
    SCHEMA:各種對象的集合

二、系統權限:
1、超過80個權限可用。
2、DBA有最高的系統權限:
    CREATE NEW USER
    REMOVE USERS
    REMOVE ANY TABLE
    BACKUP ANY TABLE
              
三、創建用戶
1、CREATE USER user IDENTIFIED BY password;
2、系統權限:
    CREATE SESSION Connect to the database.
    CREATE TABLE Create tables in the user’s schema.
    CREATE SEQUENCE Create a sequence in the user’s schema.
    CREATE VIEW Create a view in the user’s schema.
    CREATE PROCEDURE Create a stored procedure, function, or package in the user’s schema.

3、授權用戶系統權限:
    GRANT privilege [, privilege...] TO user [, user...];
    GRANT CREATE TABLE TO SCOTT;
  
四、角色的使用
 1、概念:角色是一組權限的命名,可以授予給用戶。這樣就如同給了某個用戶一個權限包。
 2、創建、授予給角色:
    CREATE ROLE MANAGER;
    GRANT CREATE TABLE,CREATE VIEW TO MANAGER;
    GRANT MANAGER TO CLARK
   
五、修改密碼:
    ALTER USER user IDENTIFIED BY password;

六、對象權限:
1、語句:
GRANT {object_priv(, object_priv...)|ALL}[(columns)]
ON object
TO {user[, user...]|role|PUBLIC}
[WITH GRANT OPTION];

2、實例:
    最簡單:
    SQL> GRANT select
    2 ON s_emp
    3 TO sue, rich;
   
    稍複雜:
    SQL> GRANT update (name, region_id)
    2 ON s_dept
    3 TO scott, manager;
   
    SQL> GRANT select, insert
    2 ON s_dept
    3 TO scott
    4 WITH GRANT OPTION;


課程 九 聲明變量
                                  
本課重點:
   1、瞭解基本的PLSQL塊和區域
   2、描述變量在PLSQL中的重要性
   3、區別PLSQL與非PLSQL變量
   4、聲明變量
   5、執行PLSQL塊

一、概述:
1、PLSQL 塊結構:
    DECLARE --- 可選    變量聲明定義
    BEGIN ---- 必選     SQL 和PLSQL 語句
    EXCEPTION ---- 可選    錯誤處理
    END;---- 必選
   
二、實例:
    declare
        vjob varchar(9);
        v_count number:=0;
        vtotal date:=sysdate +7;
        c_tax constant number(3,2):=8.25;
        v_valid boolean not null:=true;
    begin
        select sysdate into vtotal from dual;
    end;
    /
    上例中,如果沒有這個SELECT語句,會如何?
    出錯,說明必須有STATEMENTS
    如果: select sysdate from dual into vtotal ;
    同樣,也不行。而且變量與賦值的類型要匹配。
   
三、%TYPE的屬性
    聲明一個變量使之與數據庫某個列的定義相同或與另一個已經定義過的變量相同,所以%TYPE要作爲列名的後綴:如:
    v_last_name s_emp.last_name%TYPE;
    v_first_name s_emp.first_name%TYPE; --這樣做的好處是我們不必去知曉此列的類型與定義
    或:
    v_balance NUMBER(7,2);
    v_minimum_balance v_balance%TYPE := 10;
      
四、聲明一個布爾類型的變量
    1 只有TRUE、FALSE、NULL可以賦值給BOOLEAN變量
    2 此變量可以接邏輯運算符NOT、AND、OR。
    3、變量只能產生TRUE、FALSE、NULL。
實例:
    VSAL1:=50000;
    VSQL2:=60000;
    VCOMMSAL BOOLEAN:=(VSAL1<VSQL2);  --其實是把TRUE賦值給此變量。
   
五、LOB 類型的變量
    共有CLOB、BLOB、BFILE、NCLOB幾種,這裏不做爲重點。
   
六:使用HOST VARIABLES
    SQL> variable n number
    SQL> print n
    :n=v_sal /12;
  
   :n這個加了:前綴的變量不是PLSQL變量,而是HOST。
   
七、以下幾個PLSQL聲明變量,哪個不合法?
    A 、DECLARE
          V_ID NUMBER(4);
    B、DECLARE
          V_X,V_Y,V_Z VARCHAR2(9);
    C、DECLARE
       V_BIRTH DATE NOT NULL;
    D、DECLARE
       V_IN_STOCK BOOLEAN:=1;
    E、DECLARE
       TYPE NAME_TAB IS TABLE OF VARCHAR2(20) INDEX BY BINARY_INTEGER;
       DEPT_NAME NAME_TAB;

    上面的習題我會在下章給出答案,這也正是聲明變量的規則和難點。


課程 十 寫執行語句
                                  
本課重點:
   1、瞭解PLSQL執行區間的重要性
   2、寫執行語句
   3、描述嵌套塊的規則
   4、執行且測試PLSQL塊
   5、使用代碼慣例
   
一、PLSQL 塊的語法規則:
    1、語句可以跨躍幾行。
    2、詞彙單元可以包括:分隔符、標識符、文字、和註釋內容。
    3、分隔符: +-*/=<>||....
    4、標識符:
        最多30個字符,不能有保留字除非用雙引號引起。
        字母開頭,不與列同名。
    5、文字串:如 V_ENAME:='FANCY';要用單引號括起來。
        數值型可以用簡單記數和科學記數法。
    6、註釋內容:單行時用--    多行用/*   */
        與C很相似

二、SQL函數在PL/SQL的使用:
1、可用的:單行數值型、字符型和轉換型,日期型。
2、不可用的:最大、最小、DECODE、分組函數。
實例:
    BEGIN
     SELECT TO_CHAR(HIREDATE,'MON,DD,YYYY') FROM EMP;
    END;
    V_comment:=user||':'||sysdate; -- 會編譯出錯
    V_comment:=user||':'||to_char(sysdate); --正確
   
如果有可能,PLSQL都會進行數據一致性的轉換,但ORACLE推薦你應該進行顯示的轉換,因爲這樣會提高性能。

三、嵌套塊和變量作用區域
1、執行語句允許嵌套時嵌套。
2、嵌套塊可以看作正常的語句塊。
3、錯誤處理模塊可以包括一個嵌套塊
4、exponential指數 邏輯、算數、連接、小括號
5、看正面實例:
    declare
    vjob varchar(9);
    v_count number:=0;
    vtotal date:=sysdate +7;
    c_tax constant number(3,2):=8.25;
    v_valid boolean not null:=true;
    ttt vtotal%type;
    begin
    --select sysdate into vtotal from dual;--體會有無此句與結果的影響
    dbms_output.put_line (vtotal);
    end;
    /

*注意:在執行塊之前,要在SQL PLUS中執行:SET SERVEROUTPUT ON

三、以實例來說明函數的參數聲明作用域
    declare
       v_weight number(3):=600;
    v_message varchar2(255):='product10000';
    begin
    declare
       --sub-block
    v_weight number(3):=1;
    v_message varchar2(255):='pro300';
    begin
    v_weight:=v_weight +1;
    end;
    v_weight:=v_weight +1;
    v_message:=v_message || 'my name';
    end;
    /

子塊中的V_WEIGHT值爲 2
我們可以在子塊中加入:dbms_output.put_line('subblock value is '||v_weight);
在主體中加入:dbms_output.put_line('main value is '||v_weight);
我們發現MAINBLOCK中V_WEIGHT爲 601

改動:
1、在主塊的聲明中加 v_date date default sysdate;
在子塊中加入:dbms_output.put_line('subblock date value is '||v_date);
執行結果:subblock date value is 22-11月-01

*說明:主塊中的變量,如果子塊中沒有同名變量聲明,則繼承主塊中的聲明和初始化值;

2、在子塊中加入:v_sub char(9);
dbms_output.put_line('subblock char value is '||v_sub);
此時正常輸出。
在主塊中加入:dbms_output.put_line('main char value is '||v_sub);
輸出:ORA-06550: 第 21 行, 第 45 列:
PLS-00201: 必須說明標識符 'V_SUB'

*說明:
子塊中聲明的變量主塊中並不知曉,因此出錯。瞭解了此實例,一切情況的變量的值的走向就都明瞭了。
 

課程 十一 與ORACLE SERVER交互
                                  
本課重點:
   1、在PLSQL中成功的寫SELECT語句
   2、動態聲明PLSQL變量類型與SIZE
   3、在PLSQL中寫DML語句
   4、在PLSQL中控制事務
   5、確定DML操作的結果
   
一、PLSQL中的SQL語句:
    SELECT、DML、COMMIT、ROLLBACK、SAVEPOINT、CURSOR
    特殊強調:PLSQL不支持DCL,不要問爲什麼。(DBMS_SQL package allows you to issue DDL and DCL statements.)

二、SELECT
    SELECT select_list INTO variable_name | record_name
    FROM table WHERE condition;
例:
    SQL> r
    1 declare
    2 v_deptno number(2);
    3 v_loc varchar2(15);
    4 begin
    5     select deptno,loc
    6       into v_deptno,v_loc
    7      from dept
    8      where dname='SALES';
    9 DBMS_OUTPUT.PUT_LINE (V_deptno ||' and '||v_loc);
    10* end;

    30 and CHICAGO

選取字段與變量個數和類型要一致。聲明的變量一定要在SIZE上大於返回的賦值,否則提示緩衝區溢出。
如果SELECT語句沒有返回值:ORA-01403: 未找到數據
                           ORA-06512: 在line 5
如果有多個值返回:ORA-01422: 實際返回的行數超出請求的行數
這些我們到了錯誤處理時會逐一講解。
例:
上面的例子可以改爲:
    declare
       v_deptno dept.deptno%type;
       v_loc dept.loc%type;
    begin
         select deptno,loc
            into v_deptno,v_loc
            from dept
            where dname='SALES';
       DBMS_OUTPUT.PUT_LINE (V_deptno ||' and '||v_loc);
    end;
    /

這樣,可以在未知其他字段大小和類型的時候定義變量,提高兼容性。

三、DML 操作:
1、實例:
    declare
        v_empno emp.empno%type;
    begin
        select max(empno)
         into v_empno
         from emp;
        v_empno:=v_empno+1;
         insert into emp(empno,ename,job,deptno)
           values(v_empno,'asdfasdf','ddddd',10);
    end;
    /
   
   這樣也可以實現如SEQUENCE一樣的編號唯一遞增。

2、更新和刪除:
這個較爲簡單:
    DECLARE
        V_DEPTNO EMP.DEPtno%type :=10;
    begin
        delete from emp where deptno=v_deptno;
    end;
    /

PLSQL首先檢查一個標識符是否是一個數據庫的列名,如果不是,再假定它是一個PLSQL的標識符。所以如果一個PLSQL的變量名爲ID,列中也有個ID,如:
    SELECT date_ordered, date_shipped
    INTO date_ordered, date_shipped
    FROM s_ord
    WHERE id = id;
   
就會返回TOO MANY ROWS,這是要儘量避免的。   

四、SQL CURSOR
遊標是一個獨立SQL工作區,有兩種性質的遊標:
隱式遊標: 當PARSE 和EXECUTE 時使用隱式遊標。
顯式遊標: 是由程序員顯式聲明的。
遊標的屬性:
    SQL%ROWCOUNT:一個整數值,最近SQL語句影響的行數。
    SQL%FOUND    BOOLEAN屬性,如果爲TRUE,說明最近的SQL STATEMENT有返回值。
    SQL%NOTFOUND 與SQL%FOUND相反
    SQL%ISOPEN   在隱式遊標中經常是FALSE,因爲執行後立即自動關閉了。
   
    SQL> variable row_de number
    SQL> r
    1 declare
    2    v_deptno number:=10;
    3 begin
    4      delete from emp where
    5       deptno=v_deptno;
    6       :row_de:=sql%rowcount;
    7* end;
   
PL/SQL 過程已成功完成。

    SQL> print row_de --這是一個SQL PLUS變量
    ROW_DE
    ----------
         4

這時其實並沒有真正的刪除,而是需要 COMMIT或ROLLBACK,來完成事務。
   

課程 十二 編寫控制結構語句
                                  
本課重點:
   1、結構控制的的用途和類型
   2、IF 結構
   3、構造和標識不同的循環
   4、使用邏輯表
   5、控制流和嵌套
   
一、控制執行流
可以是分支和循環:IF THEN END IF
    IF condition THEN
        statements;
    [ELSIF condition THEN
        statements;]
    [ELSE
        statements;]
    END IF;

例子:
    IF V_ENAME='OSBORNE' THEN
        V_MGR:=22;
    END IF;
這裏我們可以注意,PLSQL和C語言或JAVA在條件上的不同,=代表關係運算,而:=代表賦值。
看一個函數:
    create FUNCTION calc_val
    (v_start IN NUMBER)
    RETURN NUMBER
    IS
    BEGIN
    IF v_start > 100 THEN
    RETURN (2 * v_start);
    ELSIF v_start >= 50 THEN
    RETURN (.5 * v_start);
    ELSE
    RETURN (.1 * v_start);
    END IF;
    END calc_val;
   
現在,雖然我們尚未講解CREATE 函數或過程,但可以看到IF 條件在其中的作用。

二、注意LOGIC TABLE中的邏輯對應關係
1、NOT、AND、OR
2、任何表達式中含有空值結果都爲 NULL
3、連接字符串中含有空值會把NULL作爲 EMPTY STRING
    declare
    v_deptno dept.deptno%type;
    v_loc dept.loc%type;
    V_FLAG BOOLEAN ;
    V_REC BOOLEAN :=FALSE; --此值改爲TRUE、NULL、FALSE進行不同的比較
    V_AVA BOOLEAN:=NULL;
    begin
    V_FLAG:=V_REC AND V_AVA;
    IF V_FLAG=TRUE THEN
    DBMS_OUTPUT.PUT_LINE ('TRUE');
    ELSIF V_FLAG=FALSE THEN
    DBMS_OUTPUT.PUT_LINE ('FALSE');
    ELSE
    DBMS_OUTPUT.PUT_LINE ('NULL');
    END IF;
    end;
    /
值得注意的是:NULL AND FALSE ---> FALSE ,這是在實踐中總結出來的。

三、基本循環基礎:
1、LOOP
    statement1;
    statement2;
    . . .
    EXIT [WHEN condition];
    END LOOP;
    v_ord_id s_item.ord_id%TYPE := 101;
    v_counter NUMBER (2) := 1;
    BEGIN
    . . .
    LOOP
    INSERT INTO s_item (ord_id, item_id)
    VALUES (v_ord_id, v_counter);
    v_counter := v_counter + 1;
    EXIT WHEN v_counter > 10;
    END LOOP;

2、FOR循環:
    FOR index IN [REVERSE] lower_bound..upper_bound LOOP
    statement1;
    statement2;
    . . .
    END LOOP;

實例:
    DECLARE
    V_LOWER NUMBER:=1;
    V_UPPER NUMBER:=23;
    BEGIN
    DBMS_OUTPUT.PUT_LINE('');
    FOR I IN V_LOWER..V_UPPER LOOP
    DBMS_OUTPUT.PUT_LINE(I);
    END LOOP;
    END;
    /
   
3、WHILE 循環:
    WHILE condition LOOP
    statement1;
    statement2;
    . . .
    END LOOP;
4、循環是可以多層嵌套的。可以用<<LABEL>>做循環的標籤。
    ...
    BEGIN
    <<Outer–loop>>LOOP
    v_counter :=v_counter+1;
    EXIT WHEN v_counter>10;
    <<Inner–loop>>LOOP
    ...
    EXIT Outer_loop WHEN total_done = ’YES’;
    –– Leave both loops
    EXIT WHEN inner_done = ’YES’;
    –– Leave inner loop only
    ...
    END LOOP Inner_Loop;
    ...
    END LOOP Outer_loop;
    END;
  
總結:本章內容較爲繁雜,雖然不是很難,而且多數與其他高級語言有某種共性,但大家要多多練習,用實踐來檢驗對某些含糊的猜測。


課程十三 使用組合數據類型* 遊標操縱數據

本課重點:
1、創建用戶自定義的PLSQL記錄
2、利用%ROWTYPE屬性來創建記錄
3、創建PLSQL表
4、描述記錄、表、記錄的表之間的區別

一、合成數據類型
1、類型分爲PLSQL記錄和PLSQL表
2、包含內部組件
3、可重用

二、PLSQL記錄
與3GL中的記錄結構相似,與數據庫表是兩回事
是一個方便的途徑FETCH一些行FROM一個表來進行相關處理。
標準語法格式我們暫不介紹,因爲每本書上均有。
看例子:
    declare
    vjob varchar(9);
    v_count number:=0;
    vtotal date:=sysdate +7;
    c_tax constant number(3,2):=8.25;
    v_valid boolean not null:=true;
    ttt vtotal%type;
    type emp_record_type is record
    (empno number not null:=100,
    ename emp.ename%type,
    job emp.job%type);
    emp_record emp_record_type;
    begin
    --select sysdate into vtotal from dual;--體會有無此句與結果的影響
    dbms_output.put_line (vtotal);
    end;
    /
   
主要看TYPE RECORD出現的位置。每一個例子都是可以成功執行的。
我們也可以利用原有的表結構:
DECLARE
EMP_RECORD EMP%ROWTYPE;

遊標操縱數據

PLSQL遊標提供了一種從數據庫提取多行數據,然後對每行數據進行單獨處理的方法。

一、兩種遊標:
顯式遊標
隱式遊標
  
二、顯式遊標:操縱步驟如下:聲明遊標、打開遊標、從遊標中取回數據、關閉遊標
  
三、聲明遊標:
  DECLARE CURSOR_NAME
  IS
  SELECT STATMENT
能夠控制遊標的,唯一參數是INIT.ORA中的OPEN_CURSORS,我原來以爲是客戶端最多可以打開多少個遊標,但有

本書上講這是用於管理遊標的內存的數量。
  DECLARE
  CURSOR C_NAME
  IS
  SELECT ENAME FROM EMP
  WHERE DEPTNO IN (SELECT DEPTNO FROM DEPT
  WHERE CITY_ID=‘BJ’)
--- 說明遊標可以用子查詢

四、打開遊標
  OPEN CURSOR_NAME;
  這時遊標將它的指針指向活動集的開始,指針指向第一條記錄的前面是因爲它還沒有執行FETCH命令。如果試圖打開一個已經打開的遊標,將出錯:
  ORA-06511:PL/SQL:CURSOR ALREADY OPEN
  我們可以這樣:
  IF NOT C_NAME%ISOPEN
  THEN
  OPEN C_NAME;
  END IF;

五、從遊標中取回數據
  FETCH CURSOR_NAME INTO RECOR-LIST;
  關閉遊標:CLOSE CURSOR_NAME

六、實例:
  DECLARE
  myname varchar2(22);
  CURSOR C_NAME
  IS
  SELECT ENAME FROM EMP;
  begin
  IF NOT C_NAME%ISOPEN
  THEN
  OPEN C_NAME;
  end if;
  LOOP
  FETCH c_name into myname;
  dbms_output.put_line (myname);
  exit when c_name%notfound;
  end loop;
  close c_name;
  end;
  /--我們將對以上程序進行變形,形成複雜的光標利用。

  DECLARE
  myname varchar2(22);
  thisdeptno scott.emp.deptno%type;
  CURSOR C_NAME
  IS
  SELECT ENAME,deptno FROM EMP order by deptno desc;
  begin
  IF NOT C_NAME%ISOPEN
  THEN
  OPEN C_NAME;
  end if;
  LOOP
  FETCH c_name into myname,thisdeptno;
  dbms_output.put_line (myname||','||thisdeptno || ',' || to_char(c_name%rowcount));
  exit when c_name%notfound;
  end loop;
  dbms_output.put_line ('the Total record is fetched is ' || to_char(c_name%rowcount));
  close c_name;
  end;
  /
  我們增加變量,進行用了排序,使用了光標屬性,大家看結果發生的變化,想想爲什麼。
  實例精華!!!: 
   
    DECLARE
  myname varchar2(22);
  ii number;
  thisdeptno scott.emp.deptno%type;
  CURSOR C_NAME
  IS
  SELECT * FROM EMP order by deptno desc;
  emp_record c_name%rowtype;
  begin
  ii:=1;
  for emp_record in c_name loop
  dbms_output.put_line(ii);
  ii:=ii+1;
  end loop;
  end;
  /
  --這裏使用了遊標FOR循環,在FOR循環的開始,進行、和END LOOP,分別隱式進行了遊標的打開、FETCH和CLOSE。
  
我們甚至可以不聲明遊標:FOR emp_record in (SELECT * FROM DEPT) loop
這種技術被稱爲顯式遊標的自動化。
在上面,我們可以將一個表的所有字段輸出,如我們將PUT_LINE的II改爲emp_record.ename,就可以輸出一個字段內容。
這種方式非常簡單而且效率較高。
  
----------------
爲了測試光標屬性的重要性,我們做一個以下的過程:
  create or replace PROCEDURE change_salary
  (v_emp_id IN NUMBER, -- formal parameters
  v_new_salary IN NUMBER)
  IS
  BEGIN -- begin PL/SQL block
  UPDATE emp
  SET sal = v_new_salary
  WHERE empno = v_emp_id;
  COMMIT;
  END change_salary;
  /

  這樣,我們在匿名塊中,
  UPDATE DEPT
  SET DNAME='MY DEPT' WHERE ....;
  IF SQL%FOUND THEN
  COMMIT;
  ELSE
  change_salary(7369,9000);
  END IF;


我們看到我們通過流程控制了不同的執行結果,對於過程,我們可以用以下幾種方法調用:
在SQLPLUS中:
    CALL change_salary(7369,9000);
  EXECUTE change_salary(7369,9000);
在一個塊中,如:
  begin
  change_salary(7369,9000);
  end;
  /


最後一課 異常處理

本章重點:
    1、定義PLSQL異常
    2、列舉不同的異常處理方法
    3、捕獲非預期的錯誤
    4、描述異常的影響
    5、定製異常的返回信息  

一、PLSQL異常處理
異常是由ORACLE錯誤或顯式的拋出一個錯誤產生的。
如何處理:用一個處理程序來捕獲它;將它傳遞給CALLING ENVIRONMENT
   
二、異常的類型:
1、ORACLE SERVER 預定義錯誤
2、非ORACLE SERVER 預定義錯誤,但也是ORACLE SERVER 的標準錯誤
3、用戶自定義異常

三、捕捉異常的要點:
Place the WHEN OTHERS clause after all other exception handling clauses.

You can have at most one WHEN OTHERS clause.

Begin exception-handling section of the block with the keyword EXCEPTION.

Define several exception handlers, each with their own set of actions, for the
block.

When an exception occurs, PL/SQL will process only one handler before leaving
the block.

  EXCEPTION
  WHEN exception1 [OR exception2 . . .] THEN
  statement1;

四、常用錯誤:
  NO_DATA_FOUND ORA-01403
  TOO_MANY_ROWS ORA-01422
  INVALID_CURSOR ORA-01001
  ZERO_DIVIDE ORA-01476
  DUP_VAL_ON_INDEX ORA-00001

五、實例
  PROCEDURE elim_inventory
      (v_product_id IN s_product.id%TYPE) IS
      v_id s_product.id%TYPE;
  BEGIN
      SELECT id INTO v_id FROM s_product WHERE id = v_product_id;
      DELETE FROM s_inventory
      WHERE product_id = v_product_id;
      COMMIT;
      EXCEPTION
      WHEN NO_DATA_FOUND THEN
      ROLLBACK;
      TEXT_IO.PUT_LINE(TO_CHAR(v_product_id)||’ is invalid.’);
      WHEN TOO_MANY_ROWS THEN
      ROLLBACK;
      TEXT_IO.PUT_LINE(’Data corruption in S_PRODUCT.’);
      WHEN OTHERS THEN
      ROLLBACK;
      TEXT_IO.PUT_LINE(’Other error occurred.’);
  END elim_inventory;
  在SCOTT環境中使用要稍加改動

六、使用non-predefined Oracle7 Server error
  DECLARE
  E_PRO  EXCEPTION;
  PRAGMA EXCEPTION_INIT(E_PRO,ERROR_NUMBER);
  BEGIN
  ......
  EXCEPTION
  WHEN E_PRO THEN
  DBMS_OUTPUT.PUT_LINE('ASDLKFJKASDJFASJDFLKASDF');
  ......
  END;

七、用戶自定義
  exception EXCEPTION;
  RAISE exception;  EXCEPTION
  WHEN E_PRO THEN
  DBMS_OUTPUT.PUT_LINE('ASDLKFJKASDJFASJDFLKASDF');
  ......
  END;  
這裏,只有用戶自定義異常是要顯式聲明的,其他兩個不用。在SUN OS5.8中,進行SVRMGRL> OERR ORA 01840 可返回信息或查錯誤代碼:
  HTTP://TECHNET.ORACLE.COM/DOC/SERVER.815/A67785/E1500.HTM

說回來,以下兩個函數:
 SQLCODE ----Returns the numeric value for the error code. You can assign it to a NUMBER variable.
 SQLERRM ----Returns character data conta

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章