MySQL 存儲過程和函數

来源:http://www.cnblogs.com/chenmh/archive/2016/02/19/5201473.html
-Advertisement-
Play Games

概述 一提到存儲過程可能就會引出另一個話題就是存儲過程的優缺點,這裡也不做討論,一般別人問我我就這樣回答你覺得它好你就用它。因為mysql中存儲過程和函數的語法非常接近所以就放在一起,主要區別就是函數必須有返回值(return),並且函數的參數只有IN類型而存儲過程有IN、OUT、INOUT這三種類


概述  

一提到存儲過程可能就會引出另一個話題就是存儲過程的優缺點,這裡也不做討論,一般別人問我我就這樣回答你覺得它好你就用它。因為mysql中存儲過程和函數的語法非常接近所以就放在一起,主要區別就是函數必須有返回值(return),並且函數的參數只有IN類型而存儲過程有IN、OUT、INOUT這三種類型。

語法  

 創建存儲過程和函數語法

CREATE PROCEDURE sp_name ([proc_parameter[,...]])
    [characteristic ...] routine_body
 
CREATE FUNCTION sp_name ([func_parameter[,...]])
    RETURNS type
    [characteristic ...] routine_body
    
    proc_parameter:
    [ IN | OUT | INOUT ] param_name type
    
    func_parameter:
    param_name type
 
type:
    Any valid MySQL data type
 
characteristic:
    LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
  | COMMENT 'string'
 
routine_body:
    Valid SQL procedure statement or statements

語法來自官方自帶的參考手冊,characteristic語法塊是需要註意的地方,先用一個例子來介紹。

例子:

#創建資料庫
DROP DATABASE IF EXISTS Dpro;
CREATE  DATABASE Dpro
CHARACTER SET utf8
;

USE Dpro;

#創建部門表
DROP TABLE IF EXISTS Employee;
CREATE TABLE Employee
(id INT NOT NULL PRIMARY KEY COMMENT '主鍵',
 name VARCHAR(20) NOT NULL COMMENT '人名',
 depid INT NOT NULL COMMENT '部門id'
);

#插入測試數據
INSERT INTO Employee(id,name,depid) VALUES(1,'',100),(2,'',101),(3,'',101),(4,'',102),(5,'',103);
#創建存儲過程
DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid; END$$ DELIMITER ;
#執行存儲過程 CALL Pro_Employee(
101,@pcount); SELECT @pcount;

 語法解釋:

在創建存儲過程的時候一般都會用DELIMITER$$.....END$$ DELIMITER ;放在開頭和結束,目的就是避免mysql把存儲過程內部的";"解釋成結束符號,最後通過“DELIMITER ;”來告知存儲過程結束。

主要解釋characteristic部分:

LANGUAGE SQL:用來說明語句部分是SQL語句,未來可能會支持其它類型的語句。

[NOT] DETERMINISTIC:如果程式或線程總是對同樣的輸入參數產生同樣的結果,則被認為它是“確定的”,否則就是“非確定”的。如果既沒有給定DETERMINISTIC也沒有給定NOT DETERMINISTIC,預設的就是NOT DETERMINISTIC(非確定的)CONTAINS SQL:表示子程式不包含讀或寫數據的語句。

NO SQL:表示子程式不包含SQL語句。

READS SQL DATA:表示子程式包含讀數據的語句,但不包含寫數據的語句。

MODIFIES SQL DATA:表示子程式包含寫數據的語句。

SQL SECURITY DEFINER:表示執行存儲過程中的程式是由創建該存儲過程的用戶的許可權來執行。

SQL SECURITY INVOKER:表示執行存儲過程中的程式是由調用該存儲過程的用戶的許可權來執行。(例如上面的存儲過程我寫的是由調用該存儲過程的用戶的許可權來執行,當前存儲過程是用來查詢Employee表,如果我當前執行存儲過程的用戶沒有查詢Employee表的許可權那麼就會返回許可權不足的錯誤,如果換成DEFINER如果存儲過程是由ROOT用戶創建那麼任何一個用戶登入調用存儲過程都可以執行,因為執行存儲過程的許可權變成了root)

COMMENT 'string':備註,和創建表的欄位備註一樣。

註意:在編寫存儲過程和函數時建議明確指定上面characteristic部分的狀態,特別是存在複製的環境中,如果創建函數不明確指定這些狀態會報錯,從一個非複製環境將帶函數的資料庫遷移到複製環境的機器上如果沒有明確指定DETERMINISTIC, NO SQL, or READS SQL DATA該三個狀態也會報錯。

報錯示例

Error Code: 1418. This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)

這個報錯就是上面註意部分說的問題。原來是因為在主從複製的兩台MySQL伺服器中開啟了二進位日誌選項log-bin,slave會從master複製數據,而一些操作,比如function所得的結果在master和slave上可能不同,所以存在潛在的安全隱患。因此,在預設情況下回阻止function的創建。

解決辦法有兩種:

1.將log_bin_trust_function_creators參數設置為ON,這樣一來開啟了log-bin的MySQL Server便可以隨意創建function。這裡存在潛在的數據安全問題,除非明確的知道創建的function在master和slave上的行為完全一致。
  設置該參數可以用動態的方式或者指定該參數來啟動資料庫伺服器或者修改配置文件後重啟伺服器。需註意的是,動態設置的方式會在伺服器重啟後失效。
  mysql> show variables like 'log_bin_trust_function_creators';
  mysql> set global log_bin_trust_function_creators=1;
  另外如果是在master上創建函數,想通過主從複製的方式將函數複製到slave上則也需在開啟了log-bin的slave中設置上述變數的值為ON(變數的設置不會從master複製到slave上,這點需要註意),否則主從複製會報錯。

2.明確指明函數的類型
  1 DETERMINISTIC 不確定的
  2 NO SQL 沒有SQl語句,當然也不會修改數據
  3 READS SQL DATA 只是讀取數據,當然也不會修改數據
比如:CREATE DEFINER=`username`@`%` READS SQL DATA FUNCTION `fn_getitemclock`(i_itemid bigint,i_clock int,i_pos int) RETURNS int(11)...
這樣一來相當於明確的告知MySQL伺服器這個函數不會修改數據,因此可以在開啟了log-bin的伺服器上安全的創建並被覆制到開啟了log-bin的slave上。

 修改存儲過程函數語法

ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
 
characteristic:
    { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
  | COMMENT 'string'

刪除存儲過程函數語法

DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

查看存儲過程和函數

1.查看存儲過程狀態


SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']
show procedure status like 'Pro_Employee' \G

2.查看存儲過程和函數的創建語法

SHOW CREATE {PROCEDURE | FUNCTION} sp_name

SHOW CREATE PROCEDURE Pro_Employee \G;

3.查看存儲過程和函數詳細信息

SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_NAME='Pro_Employee' \G;

總結  

 存儲過程和函數語法不難理解,但是往往存儲過程中不單單隻包含這種簡單的查詢語法,還會嵌套迴圈語句、變數、報錯處理、事務等,下一篇文章會單獨講變數,將變數的知識加入到存儲過程,包括變數的聲明和報錯處理,歡迎關註。

 

 

 

 

備註:

    作者:pursuer.chen

    博客:http://www.cnblogs.com/chenmh

本站點所有隨筆都是原創,歡迎大家轉載;但轉載時必須註明文章來源,且在文章開頭明顯處給明鏈接。

《歡迎交流討論》


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 代碼: 輸出結果 補充: reg.lastIndex:下一次正則捕獲的開始查找的索引位置 ->正則的懶惰性就是因為預設情況下lastIndex值都是0,我們不管執行幾次exec,都是從字元串的開始位置查找,那麼每一次捕獲到的都是第一個符合的內容
  • 今天看了關於js閉包方面的文章,還是有些雲里霧裡,對於一個菜鳥來說,學習閉包確實有一定的難度,不說別的,能夠在網上找到一篇優秀的是那樣的不易。 當然之所以閉包難理解,個人覺得是基礎知識掌握的不牢,因為閉包牽扯到一些前面的東西,比如作用域\等等,如果連基本的作用域都沒有弄清楚,自然不可能搞懂閉包,還有
  • [1]基本術語 [2]構造行框 [3]行內非替換元素 [4]行內替換元素
  • 這裡講的不會太多, 因為所有的語言都是一樣的, 一些基本的東西, 所以就隨便寫寫. 變數 變數就是可變的量, 編程角度理解就是用於存儲某種/某些數值的存儲器. 我們可以把變數具象理解為一個盒子, 而我們給的值就是盒子裡面的東西, 這個盒子在那裡不動, 而我們是可以改變盒子裡面的東西的. 變數的命名規
  • var BrowserMatch = { init: function () { this.browser = this.getBrowser().browser || "An Unknown Browser"; this.version = this.getBrowser().version ||
  • 之前寫過一篇博文,《不好的MySQL過程編寫習慣》(http://www.cnblogs.com/wingsless/p/5041838.html)。這篇博文里強調了不要迴圈的提交事務,儘量將可以放在一起的SQL同一個事務提交,會快很多很多。博文中提到了redo的問題,因此,結合最近編寫新員工培訓材
  • 最近一段時間在準備新員工培訓的材料,本來打算介紹介紹概念就OK的,但是既然寫了事務的章節,就特別想介紹一下鎖,介紹了鎖,就忍不住想介紹一下Next-Key Lock。 大家知道,標準的事務隔離級別有READ UNCOMMITTED,READ COMMITTED,REPEATED READ和SERIA
  • SQL Server代理是所有實時資料庫的核心。代理有很多不明顯的用法,因此系統的知識,對於開發人員還是DBA都是有用的。這系列文章會通俗介紹它的很多用法。 在這個系列的上篇文章里,你學習如何使用SQL Server代理作業活動監視器監視作業活動和查看作業歷史。對於你的SQL Server代理作業進
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...