第10章 存儲(chǔ)過程

target

掌握什么是存儲(chǔ)過程
掌握存儲(chǔ)過程的作用
掌握存儲(chǔ)過程的創(chuàng)建
掌握存儲(chǔ)過程的修改與刪除

1. 什么是存儲(chǔ)過程

存儲(chǔ)過程在數(shù)據(jù)庫開發(fā)中使用比較頻繁,它有著普通SQL語句不可替代的作用。

1.1 認(rèn)識(shí)存儲(chǔ)過程

存儲(chǔ)過程可以通俗地理解為是存儲(chǔ)在數(shù)據(jù)庫服務(wù)器中的封裝了一段或多段SQL語句的PL/SQL代碼塊。在數(shù)據(jù)庫中有一些是系統(tǒng)默認(rèn)的存儲(chǔ)過程,那么可以直接通過存儲(chǔ)過程的名稱進(jìn)行調(diào)用。另外,存儲(chǔ)過程還可以在編程語言中調(diào)用,如Java、C#等編程語言。

1.2 存儲(chǔ)過程的作用

  • 簡化復(fù)雜的操作。

    存儲(chǔ)過程可以把需要執(zhí)行的多條SQL語句封裝到一個(gè)獨(dú)立單元中,用戶只需調(diào)用這個(gè)單元就能達(dá)到目的。這樣就實(shí)現(xiàn)了一人編寫多人調(diào)用,同時(shí)縮短了平均開發(fā)周期,為公司節(jié)省了成本。

  • 增加數(shù)據(jù)獨(dú)立性。

    與視圖的效果類似,利用存儲(chǔ)過程可以把數(shù)據(jù)庫基礎(chǔ)數(shù)據(jù)和程序 (或用戶)隔離開來,當(dāng)基礎(chǔ)數(shù)據(jù)的結(jié)構(gòu)發(fā)生變化時(shí),可以修改存儲(chǔ)過程,這樣對程序來說基礎(chǔ)數(shù)據(jù)的變化是不可見的,也就不需要修改程序代碼了。

  • 提高安全性

    使用存儲(chǔ)過程有效地降低了錯(cuò)誤出現(xiàn)的幾率。如果不使用存儲(chǔ)過程要想實(shí)現(xiàn)某項(xiàng)操作可能需要執(zhí)行多條單獨(dú)的SQL語句,而過多的執(zhí)行步驟很可能造成更高的出錯(cuò)幾率。不僅如此,實(shí)際工作中開發(fā)人員的水平參差不齊,由高水平的人編寫存儲(chǔ)過程,水平較低的人員直接調(diào)用,這樣就能避免很多不必要的錯(cuò)誤發(fā)生。此外,存儲(chǔ)
    過程也可以進(jìn)行權(quán)限設(shè)置。

  • 提高性能。完成一項(xiàng)復(fù)雜的功能可能需要多條SQL語句,同時(shí)SQL每次執(zhí)行都需要編譯, 而存儲(chǔ)過程可以包含多條SQL語句,而且創(chuàng)建完成后只需要編譯一次,以后就可以直接調(diào)用,從這方面來看存儲(chǔ)過程可以提高性能。如果程序語言要實(shí)現(xiàn)某項(xiàng)比較復(fù)雜的功能, 它會(huì)多次連接數(shù)據(jù)庫,在使用存儲(chǔ)過程的情況下,程序只需連接一次就能達(dá)到目的。

1.3 存儲(chǔ)過程的語法

CREATE ( OR REPLACE ] PROCEDURE [ schema. ] procedure_name
[parameter_name [ [ IN ] datatype [ { := | DEFAULT } expression ] 
    | { OUT | IN OUT } ( NOCOPY ] datatype
  ] [,...]
    { is | as}
  body;

其中各項(xiàng)參數(shù)介紹如下:

  • OR REPLACE:表示如果指定的過程已經(jīng)存在,則覆蓋同名的存儲(chǔ)過程。

  • schema:表示該存儲(chǔ)過程的所屬機(jī)構(gòu)。

  • procedure_name:創(chuàng)建存儲(chǔ)過程的名稱。

  • parameter_name:表示存儲(chǔ)過程中的參數(shù)名稱。

  • [IN] datatype [ { := I DEFAULT } expression ]:整個(gè)這段語法表示傳入?yún)?shù)的數(shù)據(jù)類型以及默認(rèn)值。其中,datatype項(xiàng)表示參數(shù)的數(shù)據(jù)類型,[{ := I DEFAULT } expression ] 項(xiàng)表示參數(shù)的默認(rèn)值的寫法。

  • { OUT | IN OUT } [ NOCOPY ] datatype:表示存儲(chǔ)過程的參數(shù)類型,不過和上面介紹 的IN有所區(qū)別。其中,OUT表示輸出參數(shù),IN OUT表示既可輸入也可輸出的參數(shù), datatype依舊表示參數(shù)類型。

  • { IS | AS }:連接詞。

  • BODY:表示函數(shù)體,是存儲(chǔ)過程的具體操作部分,通常在begin...end中。

注意:

存儲(chǔ)過程的參數(shù)默認(rèn)類型是IN型的,也就是說是傳入型的。

創(chuàng)建存儲(chǔ)過程需要有CREATE PROCEDURE權(quán)限。

2. 在SQL *Plus中創(chuàng)建存儲(chǔ)過程

2.1 hello world存儲(chǔ)過程

create procedure helloworld as
begin
    dbms_output.put_line('Hello Wolrd');
end;
/

執(zhí)行效果:

① serveroutput設(shè)置

要想讓dbms_output.put_line成功輸出,需要把serveroutput選項(xiàng)設(shè)置為ON狀態(tài)。默認(rèn)情況是OFF狀態(tài)的??梢詧?zhí)行如下語句查看:

show serveroutput

打開輸出設(shè)置:

set serveroutput on

② 執(zhí)行存儲(chǔ)過程

begin
    helloworld;
end;
/

輸出:

Hello Wolrd

PL/SQL 過程已成功完成。

還可以通過關(guān)鍵詞exec執(zhí)行存儲(chǔ)過程:

exec helloworld;

2.2 查看存儲(chǔ)過程

存儲(chǔ)過程一旦被創(chuàng)建就會(huì)存儲(chǔ)到數(shù)據(jù)庫服務(wù)器上,Oracle允許開發(fā)人員查看已經(jīng)存在的存儲(chǔ)過程腳本,這可以到視圖USER_SOURCE里査看。

??:査看存儲(chǔ)過程helloworld的腳本

SELECT * FROM USER_SOURCE WHERE NAME = 'HELLOWORLD' ORDER BY LINE;

注意:過程名需要全部大寫。

2.3 顯示存儲(chǔ)過程的錯(cuò)誤

語法:

show errors procedure produce_name;

??:故意寫錯(cuò)一個(gè)存儲(chǔ)過程,然后查看錯(cuò)誤

① 創(chuàng)建存儲(chǔ)過程:

create procedure test_err as
begin   
  dbms_output.put_lin('Hello Wolrd');
end;
/

輸出:

警告: 創(chuàng)建的過程帶有編譯錯(cuò)誤。

② 查看存儲(chǔ)過程的錯(cuò)誤細(xì)節(jié):

show errors procedure test_err;

輸出:

PROCEDURE TEST_ERR 出現(xiàn)錯(cuò)誤:

LINE/COL ERROR
-------- -----------------------------------------------------------------
3/1      PL/SQL: Statement ignored
3/13     PLS-00302: 必須聲明 'PUT_LIN' 組件

2.4 無參存儲(chǔ)過程

無參存儲(chǔ)過程就是創(chuàng)建的存儲(chǔ)過程不帶任何參數(shù),通常這種存儲(chǔ)過程用做數(shù)據(jù)轉(zhuǎn)換的幾率 比較大。

??:把表PRODUCTINFO中價(jià)格最低的3件產(chǎn)品的description字段設(shè)置成“促銷商品”,實(shí)現(xiàn)步驟如下:

(1) 將PRODUCTINFO中產(chǎn)品價(jià)格最低的3件產(chǎn)品査詢出來。

(2) 把價(jià)格最低的3件產(chǎn)品description字段加上"促銷商品”字樣。

首先為PRODUCTINFO表添加一列description:

alter table productinfo add description varchar2(100);

創(chuàng)建存儲(chǔ)過程的腳本如下:

create procedure product_update_prc as
begin
    update productinfo set description = '促銷商品'
    where productid in
    (
    select productid from (select * from productinfo order by productprice) 
    where rownum < 4
  );
  commit;
end;
/

此時(shí)的過程還沒有執(zhí)行,只是編譯通過了,執(zhí)行后數(shù)據(jù)才會(huì)修改:

exec product_update_prc;

2.5 有參存儲(chǔ)過程

存儲(chǔ)過程允許帶有參數(shù),參數(shù)的使用將增加存儲(chǔ)過程的靈活性,給數(shù)據(jù)庫編程帶來極大的方便。

存儲(chǔ)過程中如果使用了參數(shù),在執(zhí)行存儲(chǔ)過程時(shí)必須為其指定參數(shù)。參數(shù)可以是常量、變量、表達(dá)式等。

過程有輸入、輸出、輸入輸出三種參數(shù)。其中,輸入?yún)?shù) 是默認(rèn)的參數(shù),也叫IN類型的參數(shù)。

??:根據(jù)輸入的部門名稱,從表emp中搜索出該部門員工的信息,并將其打印到屏幕

create procedure emp_intype_prc(parm_deptname in varchar2) as
    cur_deptno emp.deptno%type;                                     --存放部門名稱
    cur_emp emp%rowtype;                                            --存放emp表中的行記錄

begin
    --根據(jù)部門名字查出部門編號(hào)
    select deptno into cur_deptno
    from dept where dname=parm_deptname;
    
    if sql%found then
        dbms_output.put_line(parm_deptname || ':');
    end if;
    
    --從游標(biāo)里面取值
    for my_emp_rec in 
  (
    select * from emp where deptno = cur_deptno
  )
        loop
            dbms_output.put_line('姓名:' || my_emp_rec.ename || ' 工作:' || my_emp_rec.job || ' 薪資:' || my_emp_rec.sal);
        end loop;
        
exception
    when no_data_found then
        dbms_output.put_line('沒有數(shù)據(jù)');
    when too_many_rows then
        dbms_output.put_line('數(shù)據(jù)過多');
end;
/

執(zhí)行:

SQL> exec emp_intype_prc('ACCOUNTING');
ACCOUNTING:
姓名:CLARK 工作:MANAGER 薪資:2450
姓名:KING 工作:PRESIDENT 薪資:5000
姓名:MILLER 工作:CLERK 薪資:1300

PL/SQL 過程已成功完成。

??:輸出emp表的記錄數(shù)

CREATE or replace PROCEDURE prc_empcount (empcount out number) as
BEGIN
    Select count(*) into empcount From emp;
END;
/

執(zhí)行:

SQL> variable count number;
SQL> exec prc_empcount(:count);
SQL> print count;

     COUNT
----------
        14

3. 修改存儲(chǔ)過程

修改存儲(chǔ)過程內(nèi)容要利用replace關(guān)鍵詞。

在創(chuàng)建過程中需要開發(fā)人員自行帶上or replace關(guān)鍵詞,從而完成過程的修改,也就是覆蓋。

4. 刪除存儲(chǔ)過程

語法:

drop procedure procedure_name;

??:刪除 prc_empcount

drop procedure prc_empcount;

習(xí)題

一、填空題

  1. 存儲(chǔ)過程參數(shù)分為( )、( )和( )3種類型。
  2. SQL *Plus使用( )命令來執(zhí)行存儲(chǔ)過程。
  3. SQL*Plus使用( )命令來顯示錯(cuò)誤信息。

二、選擇題

  1. OUT類型的參數(shù)以使用下哪項(xiàng)填充?( )
    A. 常量 B. 變量
    C. 初始化后的變最 D. 函數(shù)

  2. 有輸入?yún)?shù)的存儲(chǔ)過程調(diào)用時(shí)能否不帶參數(shù)?( )
    A.不能 B,能

三、簡答題

  1. 為什么使用存儲(chǔ)過程?

  2. 存儲(chǔ)過程和語句塊有什么區(qū)別?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容