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', 'hongming@qq.com', '1211555599', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');
- INSERT INTO `imooc_goddess` VALUES ('7', '小溪', '0', '34', '2016-10-03', 'hongming@qq.com', '1211555599', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');
- INSERT INTO `imooc_goddess` VALUES ('9', '小霞', null, '23', '1990-09-09', 'xiaoxia@qq.com', '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', 'jjjj@ww.com', '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', 'jkjijij@qq.com', '112323424', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');
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
3.2 调用存储过程
- 1. CAll sp_name([parameter[,.....]])
- 2. CALL sp_name[()]
- 1
- 2
- 3
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 1
- 2
SELECT f1();
- 1
- 1
- 1
在 Java 项目上调用函数(函数有返回值)时
CallableStatement cs = conn.prepareCall("{?= call f1()}");
- 1
- 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
- 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
- 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
- 1
- 2
- 3
- 4
语句中的
DEFINER=`root`@`localhost`
- 1
- 1
- 1
是数据库自己默认添加的。
复制数据定义语言创建过程时-发生错误
当我想直接复制数据定义语言,更改一个名称创建另一个存储过程时,总是创建不成功。
1、更改名称(Error)
- CREATE DEFINER=`root`@`localhost` PROCEDURE `myselectAll`()
- BEGIN
- SELECT * FROM imooc_goddess;
- END
- 1
- 2
- 3
- 4
- 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
- 1
- 2
- 3
- 4
- CREATE DEFINER={'root`@`%`} PROCEDURE `myselectAll`()
- BEGIN
- SELECT * FROM imooc_goddess;
- END
- 1
- 2
- 3
- 4
- 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
- 1
- 2
- 3
- 4
- CREATE DEFINER={root} PROCEDURE `myselectAll`()
- BEGIN
- SELECT * FROM imooc_goddess;
- END
- 1
- 2
- 3
- 4
- 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
- 1
- 2
- 3
- 4
- CREATE DEFINER=`CURRENT_USER`() PROCEDURE `myselectAll`()
- BEGIN
- SELECT * FROM imooc_goddess;
- END
- 1
- 2
- 3
- 4
- 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
- 1
- 2
- 3
- 4
3、删除DEFINER
删除DEFINER,可以创建成功
- CREATE PROCEDURE `myselectAll`()
- BEGIN
- SELECT * FROM imooc_goddess;
- END
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
然而创建函数时却可以带 DEFINER
下面的语句可以创建成功
- CREATE DEFINER=`root`@`localhost` FUNCTION `f2`(num1 SMALLINT UNSIGNED,num2 SMALLINT UNSIGNED) RETURNS float(10,2) unsigned
- RETURN (num1+num2)/2
- 1
- 2
- 1
- 2
- 1
- 2
复制数据定义语言,创建存储过程要删除DEFINER。
7 存储过程与自定义函数的区别
存储过程实现的功能要复杂一些,而函数的的针对性更强
存储的过程可以返回多个值,函数只能有一个返回值
存储过程一般独立的执行,而函数可以作为其他 SQL语句的组成部分来实现。
过程 通俗易懂的说法:它只是将其中的程序执行一遍
函数 通俗易懂的说法:它不但将其中的程序执行一遍,还返回一个值
MySQL存储过程和自定义函数、Navicat for mysql、创建存储过程和函数、调用存储过程和函数的区别的更多相关文章
- PL/Sql 中创建、调试、调用存储过程
存储过程的详细建立方法 1.先建存储过程 左边的浏览窗口选择 procedures ,会列出所有的存储过程,右击文件夹procedures单击菜单"new",弹出 template ...
- MySQL下载安装配置和Navicat for MySQL的安装配置
MySQL 一.下载 地址:MySQL :: Download MySQL Installer 选择那个几百M的msi文件下载 二.安装 第一步: 安装许可 双击安装文件,在如下图所示界面中勾选&qu ...
- CentOS下安装MySQL,Windows下使用Navicat for MySql连接
安装 查看有没有安装过: yum list installed mysql* rpm -qa | grep mysql* 查看有没有安装包: yu ...
- 数据库之mysql篇(4)—— navicat操作mysql
navicat 1.简介: navicat是一个软件,旗下针对不同数据库有不同的软件版本,支持以下数据库,还是挺厉害的: 这里我采用navicat for mysql版本.实现图形化的操作mysql, ...
- Oracle 存储过程的创建,及触发器调用存储过程
一.创建存储过程 1.存储过程写法 create or replace procedure HVM_BYQ_TJ --变压器统计信息--->入库 (id in number) as begin ...
- DLL模块例1:使用.def模块导出函数,规范修饰名称,显示连接调用dll中函数
以下内容,我看了多篇文章,整合在一起,写的一个例子,关于dll工程的创建,请参考博客里另一篇文章:http://www.cnblogs.com/pingge/articles/3153571.html ...
- MySQL5.7.19 免安装配置 + Navicat for MySQL安装和破解(附全部资源)
近段时间因为工作原因安装了好多次本地MySQL,安装过程也是时有曲折,索性记录一下. 环境: Win10 家庭版 MySQL5.7.19 (链接:https://pan.baidu.com/s/1 ...
- 使用navicat for mysql图形界面操作数据库、使用node.js操作数据库写接口
1.先启动MYSQL服务 2.打开navicat for mysql, 点击链接,输入如下的内容: 3.新建数据表 4.数据库(新建一个db.js) //数据库链接配置 module.exports ...
- Navicat for MySQL 工具注册码
在使用 MySQL 客户端中,感觉 Navicat for MySQL 做的还是很不错的.鄙人比较懒,喜欢采用绿色安装的方式,百度网盘上备份的有个绿色的压缩包,解压打开需要注册,这里记录一下注册码,版 ...
随机推荐
- 清北集训Day1T3 LYK loves jumping(期望DP)
题目描述 LYK在玩一个魔法游戏,叫做跳跃魔法. 有n个点,每个点有两个属性hi和ti,表示初始高度,和下降高度.也就是说,它初始时高度为hi,一旦LYK踩在这个点上,由于重力的影响,这个点的高度会下 ...
- 微信小程序-最新获取用户基本信息方案
如果只是单纯的展示用户信息,那么最简单的方案就是 文档中组件: <open-data type="groupName" open-gid="xxxxxx" ...
- DevExpress Report 打印提示one or more margins are set outside the printable area of the page 问题解决
DevExpress Report Print的时候,出现这样的问题:one or more margins are set outside the printable area of the pa ...
- Android 强制软键盘关闭
在Android开发过程中,有时候我们会有强制关闭软键盘的需求.比如说:现在有一个文本编辑框(testEt)和一个按钮(testBtn),我们现在点击文本编辑框testEd,这时会弹出软键盘,然后我们 ...
- 坑人的SQL Server检测数字类型的函数ISNUMERIC
前几天,遇到一个十分棘手的问题,有同事提出在是字符类型的列中进行起止号计算,大体是这样的 新起号=上一条止号+1 新止号=新起号+数量 而在这一列的数据是这样的 库存 CN003?005007 000 ...
- OpenCV3 安装
Opencv 安装 本文主要说明了在ubuntu上通过源码安装Opencv3,包含各种独立接口.具体可以参照LearnOpencv: https://www.learnopencv.com/insta ...
- PhotoZoom的工具栏 图片放大不失真
使用PhotoZoom能够对数码图片无损放大,备受设计师和业内人员的青睐,它的出现时一场技术的革新,新颖的技术,简单的界面,优化的算法,使得它可以对图片进行放大而没有锯齿,不会失真.本文为您一起来认识 ...
- Client初见——python
from socket import *ip_port = ('127.0.0.1',8080)back_log = 5buffer_size = 1024tcp_client = socket(AF ...
- 为什么密信MeSince采用S/MIME加密?
S/MIME是Secure/Multipurpose Internet Mail Extensions (安全多用途互联网邮件扩展协议)的缩写,是采用PKI技术的用数字证书给邮件主题签名和加密的国标标 ...
- 更新GitHub的仓库
在GitHub上仓库已经存在且提交过,本地仓库部分更新后推送至GitHub仓库 添加,提交至本地仓库 将改动文件添加并提交到仓库 Roc@DESKTOP-AF552U2 MINGW64 /e/note ...