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 儲存過程,更改名稱,再建立新的儲存過程。
- 在 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<