數據庫原理之存儲過程和函數


一、存儲過程和函數概述

        1.1 什么是存儲過程和函數

        存儲過程(Stored Procedure)和函數(Stored Function)是在數據庫中定義一些完成特定功能的 SQL 語句集合,經過編譯后存儲在數據庫中。存儲過程和函數中可以包含流程控制語句以及各種 SQL 語句。他們可以接受參數、輸出參數、返回單個或多個結果。

        1.2 存儲過程的優點

        在 MySQL 中使用存儲過程,而不是用存儲在客戶端計算機本地的 SQL 程序,相比有以下幾點優點。

        (1)存儲過程增強了 SQL 語言的功能和靈活性。存儲過程可以使用流程控制語句編寫,有很強的靈活性,可以完成復雜的判斷和較復雜的計算。

        (2)存儲過程允許標准組件是編程。存儲過程被創建后,可以在程序中被多次調用,而不用重新編寫該存儲過程的 SQL 語句。而且數據庫專業人員可以隨時對存儲過程進行修改,對應用程序源代碼毫無影響。

        (3)存儲過程能實現較快的執行速度。如果某一操作包含大量的 SQL 代碼或分別被多次執行,那么存儲過程要比批處理的執行速度快很多,因為存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,並且給出最終被儲存在系統表中的執行計划。而批處理的 SQL 語句在每次運行時都要進行編譯和優化,速度相對要慢。

        (4) 存儲過程能夠減少網絡流量。針對同一個數據庫對象的操作(比如查詢、修改),如果這一操縱所涉及的 SQL 語句被組織成存儲過程,那么當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句從而大大減少了網絡流量並降低了網絡負載。

        (5)存儲過程可被當作一種安全機制來充分利用。系統管理員通過執行某一存儲過程的權限進行限制,能夠實現對響應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問。

二、創建存儲過程和函數

        在MySQL中,創建存儲過程和函數必須具有 CREATE ROUTINE 權限,並且 ALTER ROUTINE 和EXECUTE 權限被自動授予它的創建者。

        2.1 創建存儲過程

        使用 CREATE PROCEDURE 語句創建存儲過程,語法如下所示。

create procedure procedure_name ([proc_parameter[,...]])
[characteristic[,...]]
Routine_body

        其中,procedure_name是存儲過程的名稱;proc_parameter:存儲過程的參數列表,其形式如下:

[IN | OUT | INOUT]param_name type

         其中,IN表示輸入參數,OUT表示輸出參數,INOUT表示既可以輸入也可以輸出,默認為IN。param_name表示參數名稱。Type表示參數的類型。可以聲明一個或多個參數。

        Routine_body是包含在存儲過程中的 SQL 語句塊,可以用 BEGIN...END 來表示 SQL 代碼的開始與結束。

        characteristic該參數有多個取值,其取值說明如下。

a. LANGUAGE SQL:說明sql_statements部分是由 SQL 語言的語句組成,這也是數據庫系統默認的語言。
其他類型后續再補充

         例:創建一個存儲過程,從數據庫gradem的student表中檢索出所有籍貫是青島的學生的學號、姓名、班級號及家庭住址等信息。

mysql>USE gradem;
mysql>delimiter //
mysql>create procedure:proc_stud()
     ->reads sql data
     ->begin
     ->    select sno,sname,classno,saddress from student
     ->    where saddress like '%青島%' order by sno;
     ->end//
Query OK,  0 rows affected
mysql>delimiter ;

        執行存儲過程 "proc_stud",返回所有青島籍的學生信息。

        MySQL 中默認語句結束符為分號(;)。存儲過程中的 SQL 語句需要分號來結束。為了避免沖突,首先用"DELIMITER//"將 MySQL 的結束符設置為 //。最后再用"DELIMITER;"將結束符恢復成分號。

        例:創建一個名為 num_sc 的存儲過程,統計某位同學的考試門數,代碼如下。

mysql>delimiter //
mysql>create procedure num_sc ( in tmp_sno char(10), out count_num int )
    ->reads sql data
    ->begin
    ->    select count(*) into count_num from sc
    ->    where sno=tmp_sno;
    ->end//
Query OK,  0 affected
mysql>delimiter ;

        上述存儲過程中,輸入變量為 tmp_num,輸出變量為account_num,SELECT 語句用 ACCOUNT(*)計算某位同學的考試門數,最后將計算結果存入 account_num中。

        2.2 創建存儲函數

        使用 CREATE FUNCTION 語句創建。在 MySQL 中,存儲函數的使用方法與 MySQL 內部函數的使用方法是一樣的。換而言之,用戶自己定義的存儲函數與 MySQL 內部函數是一個性質的。區別在於,存儲函數是用戶定義的,MySQL 內部函數是開發者定義的。

        在 MySQL 中,創建存儲函數的基本語法如下。

create function func_name ([func_parameter[,...]])
    returns type
    [characteristic[,...]]
    Rountine_body

        其中各參數含義如下:

        (1)func_name:存儲函數名稱。

        (2)func_parameter:存儲函數中的參數列表。其形式與存儲過程相同,在此不再贅述。

        (3)returns type:指定返回值的類型。

        (4)Routine_body:是包含在存儲函數中的 SQL 語句塊,可以用 BEGIN...END 來表示 SQL 代碼的開始與結束。

        (5)characteristic:指定存儲函數的特性,該參數的取值與存儲過程的取值一樣。

        例:創建一個名為funct_name的存儲函數返回某班級的輔導員姓名

mysql> delimiter &&
mysql> create function func_name (class_no varchar(8))
    -> returns varchar(8)
    -> begin
    ->     return ( select header from class
    ->     where classno=class_no);
    -> end &&
Query OK,  0 rows affected
mysql> delimiter ;

        上述代碼中,該函數的參數為 class_no,返回值為 varchar 類型。 select 語句從 class 表查詢 classno 值等於 class_no 的記錄,並將該記錄的 header 字段的值返回。執行結果顯示,存儲函數已經創建成功。該函數的使用和 MySQL 內部函數的使用方法一樣。

        指定參數為 IN、0UT 或 INOUT 只對 procedure 合法,function 中總是默認為 IN 參數。 returns 子句只能對 function 做指定,對函數而言這是強制的。它用來指定函數的返回類型,而且函數體必須包含一個 return value 語句。

         2.3 調用存儲過程和函數

        在 MySQL 系統中,因為存儲過程和數據庫相關,如果要執行其他數據庫的存儲過程,需要打開相應的數據庫或指定數據庫名稱。存儲函數的調用與 MySQL 內部函數的調用方式相同。

        使用 CALL 命令調用存儲過程,語法格式如下:

call [dbname.]spname ([parameter[,...]]);

        其中,dbname 是數據庫名稱,默認為當前數據庫。sp_name 是存儲過程的名稱,parameter是指存儲過程的參數。

        例:調用存儲過程 name_sc

mysql> call num_sc ('2020030101', @num);  # 調用存儲過程
Query OK,  0 rows affected
mysql> select @num;    # 查詢返回結果

        例:調用存儲函數 func_teater

mysql> select func_teater('李斯');  # 調用存儲函數

三、管理存儲過程和函數

        3.1 查看存儲過程和函數

        查看存儲過程的狀態信息,可以使用 SHOW STATUS 語句或 SHOW CREATE 語句來查看,也可以通過查詢 information_schema 數據庫下的 Routines 來查看存儲過程和函數的信息。

        (1)利用 SHOW STATUS 語句查看。

show {procedure | function} STATUS [LIKE 'PATTERN'];

        例:查詢名為bum_sc 存儲過程的狀態

show procedure status like 'num_sc';

        (2)利用 SHOW CREATE 語句查看。

show create [procedure | function] sp_name;  # sp_name表示存儲過程或函數的名字

        SHOW STATUS 語句只能查看存儲過程或函數是操作哪一個數據庫、存儲過程或函數的名稱、名稱、類型、誰定義的、創建和修改時間、字符編碼等信息。但是,這個語句不能查詢存儲過程或函數的具體定義。如果需要查詢詳細定義,需要使用 SHOW CREATE 語句。

         (3)從information_schema.Routines 表中查看。

        存儲過程和函數的信息儲存在Information數據庫下的 Routines 表中。

select * from information_schema.Routines where routin_name = 'sp_name'

        3.2 修改存儲過程和函數

        修改存儲過程和函數是指修改已經定義好的存儲過程和函數。MySQL 中通過 ALTER PROCEDURE 語句來修改存儲過程。通過 ALTER FUNCTION 語句來修改存儲函數。

alter [procedure | function] sp_name [characteristic ...];

        characteristic 參數指定存儲函數的特性,可能的取值與創建存儲過程的參數說明相同。

        例:修改存儲過程 num_sc 的定義。將讀寫權限改為 modifies sql data,並指明調用者可以執行,代碼如下。

mysql> alter procedure num_sc
    -> modifies sql data
    -> sql security invoker;
Query OK,  0  affected

        3.3 刪除存儲過程和函數

        可以使用 DROP PROCEDURE 語法從當前的數據庫刪除用戶定義的存儲過程和函數。

drop [procedure | function] [if exists] sp_name;

        if exists子句是 MySQL 擴展,如果存儲過程或函數不存在,它可以防止發生錯誤,產生一個用 SHOW WARNING查看的警告。

        結束!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM