1. 程式人生 > >MySQL儲存過程和自定義函式、Navicat for mysql、建立儲存過程和函式、呼叫儲存過程和函式的區別

MySQL儲存過程和自定義函式、Navicat for mysql、建立儲存過程和函式、呼叫儲存過程和函式的區別

與你相遇 好幸運 
可我已失去為你淚流滿面的權利 
但願在我看不到的天際 
你張開了雙翼

1 MySQL儲存過程和函式

過程和函式,它們被編譯後儲存在資料庫,稱為永續性儲存模組(Persistent Stored Module,PSM),可以反覆呼叫,執行速度快。

1.1 儲存過程

儲存過程是由過程化 SQL 語句書寫的過程,這個過程經編譯和優化後儲存在資料庫伺服器中,因此稱它為儲存過程,使用時只要呼叫即可。

1.2 函式

這裡指自定義函式,因為是使用者自己使用過程化 SQL 設計定義的。函式和儲存過程類似,都是永續性儲存模組。函式的定義和儲存過程也類似,不同之處是函式必須指定返回型別

MySQL 命令的執行過程: 
這裡寫圖片描述

儲存過程和函式可以簡化語法分析和編譯的過程,提高執行速度。

2 我的 MySQL 資料表

資料庫名:peng 
表名: imooc_goddess

這裡寫圖片描述

我的建立資料庫、建表和插入資料 SQL 語句:

/*
Navicat MySQL Data Transfer

Source Server         : localhost_3306
Source Server Version : 50712
Source Host           : localhost:3306
Source Database       : peng

Target Server Type    : MYSQL
Target Server Version : 50712
File Encoding         : 65001

Date: 2016-10-04 20:53:44
*/
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for imooc_goddess -- ---------------------------- DROP TABLE IF EXISTS `imooc_goddess`; CREATE TABLE `imooc_goddess` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_name` varchar(30) NOT NULL, `sex` int(11) DEFAULT NULL
, `age` int(11) DEFAULT NULL, `birthday` date DEFAULT NULL, `email` varchar(30) DEFAULT NULL, `mobile` varchar(11) DEFAULT NULL, `create_user` varchar(30) DEFAULT NULL, `create_date` date DEFAULT NULL, `update_user` varchar(30) DEFAULT NULL, `update_date` date DEFAULT NULL, `isdel` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;
-- ---------------------------- -- Records of imooc_goddess -- ---------------------------- INSERT INTO `imooc_goddess` VALUES ('2', '小彭', null, '23', null, null, null, null, null, null, null, null); INSERT INTO `imooc_goddess` VALUES ('6', '胖子', '0', '78', '2016-10-03', '[email protected]', '1211555599', 'admin', '2016-10-03', 'admin', '2016-10-03', '1'); INSERT INTO `imooc_goddess` VALUES ('7', '小溪', '0', '34', '2016-10-03', '[email protected]', '1211555599', 'admin', '2016-10-03', 'admin', '2016-10-03', '1'); INSERT INTO `imooc_goddess` VALUES ('9', '小霞', null, '23', '1990-09-09', '[email protected]', '232445455', null, '2016-10-03', null, '2016-10-03', null); INSERT INTO `imooc_goddess` VALUES ('10', 'hh', '1', '23', '1990-09-09', 'jkjfskf', '12323', 'Admin', '2016-10-03', 'admin', '2016-10-03', '1'); INSERT INTO `imooc_goddess` VALUES ('11', '平', '1', '23', '2998-04-09', '[email protected]', '1323', 'admin', '2016-10-03', 'admin', '2016-10-03', '1'); INSERT INTO `imooc_goddess` VALUES ('12', '航母', '1', '23', '2333-09-09', 'jkksjkjf', '1232', 'admin', '2016-10-03', 'admin', '2016-10-03', '1'); INSERT INTO `imooc_goddess` VALUES ('13', '胖紙', '1', '23', '1991-09-09', 'jjijijij', '1323244', 'admin', '2016-10-03', 'admin', '2016-10-03', '1'); INSERT INTO `imooc_goddess` VALUES ('14', '校長', '1', '18', '1998-09-09', '[email protected]', '112323424', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

3 儲存過程的建立模板和呼叫模板

3.1 建立儲存過程模板

這裡寫圖片描述

[ ] 表示可以省略 
DEFINER 建立者,省略為預設使用者 
sp_name 為過程名 
sp_name 的引數(proc_paramenter) 可以無或多個 
routine_body 過程體 
proc_paramenter 型別 :

IN 必須在呼叫儲存過程時指定 
OUT 可以被儲存過程改變,並且可以返回 
INOUT 呼叫時指定,並且可以被改變和返回

過程體如果是複合結構,則使用 BEGIN …END 語句。

CREATE PROCEDURE sp_name(proc_paramenter)
BEGIN
routine_body
END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

3.2 呼叫儲存過程

1. CAll sp_name([parameter[,.....]])

2. CALL sp_name[()]
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

4 建立的儲存過程

儲存過程的建立的方式有很多,但是儲存過程的建立所需的程式碼都大同小異。

  • 在 電腦的 CMD 命令列建立
  • 在 Navicat 表中函式模組新建函式
  • 在 Navicat 新建查詢(類似命令列方式)

其實 Navicat for mysql 只是一個圖形化介面而已,其中的原理都是一樣的,CMD 方式還是最經典的,最基礎的。

示例

當我們登入到 MySQL 資料庫中時,可以通過SELECT VERSION();,查詢到當前 MySQL 版本資訊,如下

這裡寫圖片描述

下面是把 SELECT VERSION(); 作為一個過程體,寫入到新建的一個儲存過程中的三種方式。

方式一 CMD命令列方式

因為資料庫本來就有自己的函式,建立儲存過程名,儘量避免使用資料庫相關的名詞,可以使用比較獨特的名詞。

建立名為 v1 的儲存過程,儲存在資料庫中,建立其他儲存過程時,就不能使用 v1這個名字建立了,否則會發生重名錯誤。

這裡寫圖片描述

方式二 Navicat 新建查詢

建立名為 v3 的儲存過程

這裡寫圖片描述

方式三 Navicat 新建函式

建立名為 v2 的儲存過程

1.在函式上右擊新建函式。

這裡寫圖片描述

2.選擇過程。 
這裡寫圖片描述

3.這個儲存過程沒有引數,不填寫,點完成。 
這裡寫圖片描述

4.在過程體中輸入SELECT VERSION();,點選儲存,輸入過程名 v2 ,確認。 
這裡寫圖片描述

還是GIF圖來的快 
這裡寫圖片描述

當然,呼叫這 3 種儲存過程,都可以在 Navicat 新建查詢或 CMD 中通過

CALL v1();
CALL v2();
CALL v3();
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

來呼叫

4.1 建立不帶引數的儲存過程

在 CMD 中執行下面的語句。 
這裡寫圖片描述

4.2 建立帶有IN型別引數的儲存過程

DELIMITER 是MySQL的一個定界符,是告訴mysql直譯器,該段命令是否已經結束了,mysql可以執行了 
但是,在複合結構中,sql 語句用“;”結尾,但是我們並沒有結束輸入命令,所以通過 
DELIMITER // 
修改 預設為 “;”的定界符為”//”, 以後輸入 “//”代表命令輸入結束,mysql 可以執行了。 
DELIMITER ; 改回預設的定界符。

這裡寫圖片描述

引數名不能和資料表名相同,上面例子的 p_id不能寫成 id。 
不能更改已經儲存的儲存過程的函式體,必須先刪除該儲存過程,再建立新的儲存過程。

4.3 建立帶有 IN和OUT型別引數的儲存過程

這是一個有輸入值和返回值的儲存過程。輸入要刪除的行號 p_id ,之後資料庫計算剩餘行數 返回到 userNums 中。

1.要輸入的值為 p_id,返回的值為 userNums。 
這裡寫圖片描述

2.在過程體中輸入

DELETE FROM imooc_goddess WHERE id = p_id;
SELECT COUNT(id) FROM imooc_goddess INTO userNums;
  • 1
  • 2
  • 1
  • 2

這裡寫圖片描述

3.點選進入函式,點選執行 
這裡寫圖片描述

結果:

時間: 00:00.08

Procedure executed successfully
受影響的行: 1

Parameters: IN `p_id` int,OUT `userNums` int
14,@nums
Return values: 14, 4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

1.在 CMD 命令列的寫法

DELIMITER // 
CREATE PROCEDURE removeUserAndReturnUserNums(IN p_id INT UNSIGNED,OUT userNums INT UNSIGNED)
BEGIN
DELETE FROM imooc_goddess WHERE id = p_id;
SELECT COUNT(id) FROM imooc_goddess INTO userNums;
END
DELIMITER ; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意如果資料中含有 removeUserAndReturnUserNums 儲存過程,更改名稱,再建立新的儲存過程。

  1. 在 CMD 命令列呼叫

這裡寫圖片描述

4.4 建立帶有多個OUT型別的儲存過程

輸入年齡,返回刪除的行數,和剩餘行數。

這裡寫圖片描述

SQL 語句

CREATE PROCEDURE removeUserByAgeAndReturnInfos(IN p_age SMALLINT UNSIGNED,OUT 
deleteUsers SMALLINT UNSIGNED,OUT userCounts SMALLINT UNSIGNED)
BEGIN
DELETE FROM imooc_goddess WHERE age = p_age;
SELECT ROW_COUNT() INTO deleteUsers;
SELECT COUNT(id) FROM imooc_goddess INTO userCounts;
END
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

5 自定義函式

使用者自定義函式(user-defined function,UDP)是一種對MySQL 擴充套件的途徑,其用法與內建函式相同。

5.1 建立自定義函式模板

CREATE FUNCTION function_name
RETURNS
{STRING|INTEGER|REAL|DECIMAL}
routine_body
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

關於函式體

函式體由合法的SQL語句構成 
函式體可以是簡單的SELECT或INSERT語句 
函式體如果為複合結構則使用 BEGIN….END 語句 
複合結構可以包含宣告,迴圈,控制結構

5.2 自定義函式的建立和呼叫

1 自定義不帶引數的函式

這裡寫圖片描述

CREATE FUNCTION f1() RETURNS VARCHAR(30)
RETURN DATE_FORMAT(NOW(),'%Y年%m月%d日:%H時:%i分:%s秒');
  • 1
  • 2
  • 1
  • 2
SELECT f1();
  • 1
  • 1

在 Java 專案上呼叫函式(函式有返回值)時

CallableStatement cs = conn.prepareCall("{?= call f1()}");
  • 1
  • 1

2 自定義兩個引數的函式

輸入兩個值,計算其平均值。

CREATE FUNCTION f2(num1 SMALLINT UNSIGNED,num2 SMALLINT UNSIGNED)
RETURNS FLOAT(10,2) UNSIGNED
RETURN (num1+num2)/2;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

3 建立具有複合機構函式體的函式

插入一條新資料,user_name,返回該行的id。

CREATE FUNCTION adduser(username VARCHAR(20))
RETURNS INT UNSIGNED
BEGIN
INSERT  imooc_goddess(user_name) VALUES (username);
return LAST_INSERT_ID();
END
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

這裡寫圖片描述

6 通過 Navicat 檢視儲存過程和函式的建立語句

在 Navicat 中點開函式欄,選擇你要檢視的函式,右擊選擇物件資訊。 
這裡寫圖片描述

選擇DDL欄(資料定義語言)

這裡寫圖片描述

CREATE DEFINER=`root`@`localhost` PROCEDURE `selectAll`()
BEGIN
SELECT * FROM imooc_goddess;
END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

語句中的

DEFINER=`root`@`localhost`
  • 1
  • 1

是資料庫自己預設新增的。

複製資料定義語言建立過程時-發生錯誤

當我想直接複製資料定義語言,更改一個名稱建立另一個儲存過程時,總是建立不成功。 
1、更改名稱(Error

CREATE DEFINER=`root`@`localhost` PROCEDURE `myselectAll`()
BEGIN
SELECT * FROM imooc_goddess;
END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

2、修改DEFINER(下面的語句都是不能成功建立

CREATE DEFINER={'root`@`localhost`} PROCEDURE `myselectAll`()
BEGIN
SELECT * FROM imooc_goddess;
END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
CREATE DEFINER={'root`@`%`} PROCEDURE `myselectAll`()
BEGIN
SELECT * FROM imooc_goddess;
END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
CREATE DEFINER={root|localhost} PROCEDURE `myselectAll`()
BEGIN
SELECT * FROM imooc_goddess;
END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
CREATE DEFINER={root} PROCEDURE `myselectAll`()
BEGIN
SELECT * FROM imooc_goddess;
END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
CREATE DEFINER=root PROCEDURE `myselectAll`()
BEGIN
SELECT * FROM imooc_goddess;
END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
CREATE DEFINER=`CURRENT_USER`() PROCEDURE `myselectAll`()
BEGIN
SELECT * FROM imooc_goddess;
END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
CREATE DEFINER=CURRENT_USER PROCEDURE `myselectAll`()
BEGIN
SELECT * FROM imooc_goddess;
END
  • 1
  • 2
  • 3
  • 4
  • 1<