MYSQL存储过程和函数学习笔记
学至Tarena金牌讲师,金色晨曦科技公司技术总监沙利穆课程笔记的综合。
1. 什么是存储过程和函数
将SQL语句放入一个集合里,然后直接调用存储过程和函数来执行已经定义好的SQL语句,通过存储过程和函数,可以避免开发人员重复编写相同的SQL语句。
MYSQL存储过程和函数是保存在服务器中,在服务器中存储和执行,可以减少客户端和服务器端之间数据传输的消耗。
存储过程就是一组已经保存在数据库中的语句,并且可以随时地调用。
存储过程允许标准组件式编程,存储过程在被创建以后可以在程序中被多次调用而不必重新编写该存储过程的SQL语句,而且数据库专业人员可随时对存储过程进行修改,但对应用程序源代码毫无影响。因为应用程序源代码只包含存储过程的调用语句从而极大地提高了程序的可移植性。
1.1 什么时候要用到存储过程(存储过程的特点):
(1) 存储过程是在服务器端运行的,它的执行速度比较快。
(2) 存储过程执行一次后,就会驻留在高处缓冲存储器中,在以后的操作中,只需要从高处缓冲存储器中调用已经编译好的二进制代码来执行,这样就能提高系统的性能和响应时间。
(3) 使用存储过程,可以确保数据库的安全,因为使用存储过程可以完成数据库的所有操作,因为可以把想要进行的操作都放入SQL语句中,然后通过编程的方式来控制对数据库的访问权限。
1.2 利用mysql的存储过程比单独执行mysql的优势在哪里?好处有什么?
计算机上调用Transaction-SQL 编写的一段程序原因在于存储过程具有以下优点
1 存储过程允许标准组件式编程
存储过程在被创建以后可以在程序中被多次调用,而不必重新编写该存储过程的SQL语句,而且数据库专业人员可随时对存储过程进行修改,但对应用程序源代码毫无影响,因
为应用程序源代码只包含存储过程的调用语句,从而极大地提高了程序的可移植性
2 存储过程能够实现较快的执行速度
如果某一操作包含大量的Transaction-SQL 代码,或分别被多次执行那么存储过程要比批处理的执行速度快很多。因为存储过程是预编译的,在首次运行一个存储过程时,查询优化器对其进行分析优化,并给出最终被存在系统表中的执行计划,而批处理的Transaction-SQL 语句在每次运行时都要进行编译和优化,因此速度相对要慢一些
3 存储过程能够减少网络流量
对于同一个针对数据数据库对象的操作,如查询、修改,如果这一操作所涉及到的Transaction-SQL 语句被组织成一存储过程,那么当在客户计算机上调用该存储过程时,网络中传送的只是该调用语句,否则将是多条SQL 语句从而大大增加了网络流量降低网络负载
4 存储过程可被作为一种安全机制来充分利用
系统管理员通过对执行某一存储过程的权限,进行限制从而能够实现对相应的数据访问权限的限制,避免非授权用户对数据的访问,保证数据的安全。
2. 创建存储过程:
CREATE PROCEDURE sp_name
([proc_parameter[,…]])
[characteristic]
Routine_body
说明:
Sp_name:存储过程名称,自定义,尽量起一个有意义的名称
([proc_parameter[,…]]):需要接收或者输出的参数
[characteristic]:特性
Routine_body:要执行的代码,写在BEGIN和END中,BEGIN和END类似于函数体的{}
3.存储过程的参数:
3.1 输入输出的参数
输入输出的参数 参数的名称 参数的类型
3.1.1输入输出的参数包括:
IN:输入,把外界的数据传递到存储过程当中
OUT:输出,把存储过程的运算结果传递到外界
INOUT:输入输出,既可以把外界的数据传递到存储过程当中,又可以把存储过程的运算结果传递到外界
3.1.2参数的类型
可以是MYSQL数据库中的任意类型
3.1.3 特性
LANGUAGE SQL:默认的,说明Routine_body部分是由SQL语句注册,即数据库默认的语言
DETERMINISTIC:指明存储过程执行的结果是确定的,每次执行存储过程的时候,相同的输入会得到相同的输出。
NOT DETERMINISTIC:指明存储过程执行的结果不是确定的,每次执行存储过程的时候,相同的输入会得到不同的输出,默认情况下,结果是非确定的。
子查询使用SQL语句的限制:
CONTAINS SQL:表示子程序中可以包含SQL语句,但不包含读或写数据。默认情况下使用该限制。
NO SQL:不包含SQL语句
READS SQL DATA:包含查询数据的语句
MODIFIES SQL DATA:包含写数据的语句
--
SQL SECURITY DEFINER / INVOKER:谁有权限来执行这个存储过程,DEFINER(默认)表示只有定义者自己可以执行,INVOKER表示调用者可以执行。
3.1.4 注释
COMMENT ‘string’
‘string’:注释信息,可以在创建存储过程的时候指定注释。
4. 改变存储过程默认的定界符
通过DELIMITER来改变
例子:
DELIMITER //
CREATE PROCEDURE sp_demo1()
BEGIN
SELECT * FROM users2;
END
//
DELIMITER ;.
Query OK, 0 rows affected (0.28 sec)
说明:因为存储过程也包含了很多SQL语句,而这些SQL语句也都是以分号结尾的,为了避免定界符的冲突,所以使用DELINITER来改变定界符
注意:
(1)DELIMITER与定界符之间,一定要有一个空格,否则设置将无效。
(2)要注意每次创建存储过程结束后,要将定界符恢复为分号,这是一个好的习惯。
5.创建带参数的存储过程:
DELIMITER //
CREATE PROCEDURE age_from_user2(IN user_id INT,OUT user_age INT)
READS SQL DATA
BEGIN
SELECT age INTO user_age FROM user
WHERE id=user_id;
END
//
DELIMITER ;.
说明:
(1) INT表示参数的返回值,或者说是参数的数据类型
(2)INTO 参数名:表示将SQL语句执行的结果赋给INTO后面的参数中
创建IN参数的存储过程的例子:
查询订货量大于外界所传递进来的参数p_in的订单数据
DELIMITER //
CREATE PROCEDURE proc2(IN p_in INT)
BEGIN
SELECT * FROM `order` WHERE onum>p_in;
END
//
DELIMITER ;
创建带有OUT输出参数的例子:
DELIMITER //
CREATE PROCEDURE proc3(OUT p_out INT )
BEGIN
SELECT count(*) INTO p_out FROM custom;
END
//
DELIMITER ;
说明:INTO 参数名:表示将count(*)的结果赋给INTO后面的参数中
创建带有INOUT输入输出参数的存储过程:
DELIMITER //
CREATE PROCEDURE proc4(INOUT p_io INT)
BEGIN
SET p_io=5;
END
//
DELIMITER ;
6.创建存储函数
存储过程与存储函数本质上是相同的,都属于存储程序,也就是保存在数据库当中的程序,用的时候,都可以随时调用。
6.1 存储过程与存储函数的区别
(1)存储过程可以指定IN、OUT参数,存储函数不需要指定输入输出参数,存储函数所有的参数都属于IN参数。
(2)存储函数可以通过RETURN语句将运算的结果返回,但是存储过程不允许调用RETURN语句,存储过程可以通过调用OUT参数,将运算的结果返回给外界。
6.2 创建存储函数
CREATE FUNCTION func_name ([func_parameter[…]])
RETURNS type
[characteristic…]
Routine_body
说明:
RETURN type:表示返回值的类型
[characteristic…]:表示函数的特性,与存储过程的特性一致
例子:
DELIMITER //
CREATE FUNCTION username_from_user(user_id INT)
RETURNS VARCHAR(20)
BEGIN
RETURN (SELECT username FROM users2 WHERE id=user_id);
END
//
DELIMITER ;
说明:
RETURNS 是指定返回值的数据类型
RETURN() 是将返回结果反馈给外界。
7.调用存储过程
CALL sp_name ([parameter[,…]])
注意:
(1) 调用的时候,一定要有执行的权限
(2) 调用之后,系统执行存储过程的语句,然后将输出结果返回
例子:
CALL sp_demo1();
7.1调用有参数的存储过程:
先创建一个存储过程:
DELIMITER //
CREATE PROCEDURE age_from_user2(IN user_id INT,OUT user_age INT)
READS SQL DATA
BEGIN
SELECT age INTO user_age FROM user
WHERE id=user_id;
END
//
DELIMITER ;
然后调用这个存储过程,注意,变量用@变量名称
CALL age_from_user2(120,@use_age);
查看变量的值:
mysql> SELECT @use_age;
+----------+
| @use_age |
+----------+
| 22 |
+----------+
1 row in set (0.00 sec)
7.2调用有IN参数的存储过程:
创建IN参数的存储过程的例子:
查询订货量大于外界所传递进来的参数p_in的订单数据
DELIMITER //
CREATE PROCEDURE proc2(IN p_in INT)
BEGIN
SELECT * FROM `order` WHERE onum>p_in;
END
//
DELIMITER ;
调用有IN参数的存储过程:
SET @num=10;
CALL proc2(@num);
7.3带有OUT参数的存储过程的调用
创建带有OUT输出参数的例子:
DELIMITER //
CREATE PROCEDURE proc3(OUT p_out INT )
BEGIN
SELECT count(*) INTO p_out FROM custom;
END
//
DELIMITER ;
说明:INTO 参数名:表示将count(*)的结果赋给INTO后面的参数中
调用存储过程:
mysql> SET @amount=0;
Query OK, 0 rows affected (0.00 sec)
mysql> CALL proc3(@amount);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT @amount;
+---------+
| @amount |
+---------+
| 4 |
+---------+
1 row in set (0.00 sec)
7.4 调用有INOUT参数的存储过程
创建带有INOUT输入输出参数的存储过程:
DELIMITER //
CREATE PROCEDURE proc4(INOUT p_io INT)
BEGIN
SET p_io=5;
END
//
DELIMITER ;
调用有INOUT参数的存储过程:
mysql> SET @num=-1;
Query OK, 0 rows affected (0.00 sec)
mysql> CALL proc4(@num);
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @num;
+------+
| @num |
+------+
| 5 |
+------+
1 row in set (0.00 sec)
8.调用存储函数
调用存储函数与调用系统函数的格式是一样的。
SELECT func_name([parameter[,…]]);
例子:
创建存储函数:
DELIMITER //
CREATE FUNCTION username_from_user(user_id INT)
RETURNS VARCHAR(20)
BEGIN
RETURN (SELECT username FROM users2 WHERE id=user_id);
END
//
DELIMITER ;
调用存储函数:
mysql> SELECT username_from_user(120);
+-------------------------------------+
| username_from_user(120) |
+-------------------------------------+
| nihao |
+-------------------------------------+
1 row in set (0.05 sec)
调用存储函数例子:
先创建存储函数
DELIMITER //
CREATE FUNCTION func1(id CHAR)
RETURNS VARCHAR(10)
BEGIN
RETURN(SELECT cname FROM custom WHERE cid=id);
END
//
DELIMITER ;
调用存储函数:
mysql> SET @id='110002';
Query OK, 0 rows affected (0.00 sec)
mysql> SET @name='';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT func1(@id) INTO @name;
Query OK, 1 row affected (0.00 sec)
mysql> SELECT @name;
+--------------------------------------------+
| @name |
+--------------------------------------------+
| 湖北众合粮油工业有限公司 |
+--------------------------------------------+
1 row in set (0.00 sec)
9. 查看已创建好的存储过程和函数:
查看存储过程:SHOW PROCEDURE STATUS LIKE ‘sp_name’;
查看存储函数:SHOW FUNCTION STATUS LIKE ‘func_name’;
查看全部存储过程:SHOW PROCEDURE STATUS \G
查看全部存储函数:SHOW FUNCTION STATUS \G
注意:‘sp_name’和‘func_name’一定要加引号。
例:
SHOW PROCEDURE STATUS LIKE 'age_from_user3';
SHOW PROCEDURE STATUS LIKE 'age_from_user3'\G; (按行输出)
*************************** 1. row ***************************
Db: homework (在哪个数据库下)
Name: age_from_user3 (存储过程的名字)
Type: PROCEDURE (存储过程的类型)
Definer: root@localhost (存储过程的定义者)
Modified: 2014-11-13 20:48:11 (存储过程的修改时间)
Created: 2014-11-13 20:48:11 (存储过程的创建时间)
Security_type: DEFINER (安全类型,谁可以执行这个存储过程)
Comment: (注释)
character_set_client: gbk (客户端的字符集)
collation_connection: gbk_chinese_ci (校验字符集)
Database Collation: utf8_bin (数据库的字符集)
1 row in set (0.00 sec)
查看存储函数:
SHOW FUNCTION STATUS LIKE 'username_from_user';
SHOW FUNCTION STATUS LIKE 'username_from_user'\G;
*************************** 1. row ***************************
Db: homework
Name: username_from_user
Type: FUNCTION
Definer: root@localhost
Modified: 2014-11-13 20:40:10
Created: 2014-11-13 20:40:10
Security_type: DEFINER
Comment:
character_set_client: gbk
collation_connection: gbk_chinese_ci
Database Collation: utf8_bin
1 row in set (0.00 sec)
10.查看存储过程和存储函数的定义
SHOW CREATE PROCEDURE sp_name;
SHOW CREATE FUNCTION func_name;
例子:
SHOW CREATE PROCEDURE age_from_user3\G;
*************************** 1. row ***************************
Procedure: age_from_user3
sql_mode: NO_ENGINE_SUBSTITUTION (SQL类型)
Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `age_from_user3`(IN user_id INT,OUT user_age INT)
READS SQL DATA
BEGIN
SELECT age INTO user_age FROM users2
WHERE id=user_id;
END
character_set_client: gbk
collation_connection: gbk_chinese_ci
Database Collation: utf8_bin
1 row in set (0.00 sec)
查看函数的创建例子:
mysql> SHOW CREATE FUNCTION username_from_user\G;
*************************** 1. row ***************************
Function: username_from_user
sql_mode: NO_ENGINE_SUBSTITUTION
Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `username_from_user`(user_id INT) RETURNS varchar(20) CHARSET utf8 COLLATE utf8_bin
BEGIN
RETURN (SELECT username FROM users2 WHERE id=user_id);
END
character_set_client: gbk
collation_connection: gbk_chinese_ci
Database Collation: utf8_bin
1 row in set (0.00 sec)
11. 查看数据库information_schema中的存储过程和函数
数据库information_schema保存了所有的存储过程和存储函数,均保存在了ROUTINES表中。
(1) 切换数据库:mysql> USE information_schema;
(2) 查看ROUTINES表:mysql> SELECT * FROM ROUTINES\G
或者使用:SELECT * FROM information_schema.routines \G
可以根据查询结果的选项内容,进行条件查询:
SELECT * FROM information_schema.routines WHERE routine_type='FUNCTION' \G
12.修改存储过程和函数的属性
我们需要明白这里的修改不是修改其中的SQL语句,而是修改它的安全性以及数据访问。我们也可以通过客户端工具进行查看和修改。
ALTER PROCEDURE sp_name [COMMENT ‘string’];
ALTER FUNCTION func_name [COMMENT ‘string’];
修改存储过程:
mysql> ALTER PROCEDURE sp_demo1 COMMENT 'THIS IS A TEST';
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW PROCEDURE STATUS LIKE 'sp_demo1'\G;
修改存储函数:
ALTER FUNCTION username_from_user COMMENT'THIS IS A TEST OF FUCTION';
mysql> SHOW FUNCTION STATUS LIKE 'username_from_user'\G;
12.1 存储过程的安全性
安全类型有两个:
DEFINER:定义者,定义这个存储过程的人可以执行它,默认
INVOKER:调用者,调用这个存储过程的人可以执行它
SQL 数据访问选项有4个:
CONTAINS SQL:存储过程或者函数包含SQL语句
NO SQL: 存储过程或者函数不包含SQL语句
READS SQL DATA: 存储过程或者函数的SQL语句是读数据库的数据
MODIFIES SQL DATA: 存储过程或者函数的SQL语句是修改数据库的数据
12.2 修改存储过程和函数的安全性
修改之前先查看一下属性值:
SELECT * FROM information_schema.routines \G
然后使用ALTER 语句修改存储过程proc2的安全类型和数据访问选项:
ALTER PROCEDURE proc2
MODIFIES SQL DATA
SQL SECURITY INVOKER;
SHOW PROCEDURE STATUS LIKE 'proc2'\G
SELECT * FROM information_schema.routines \G
13. 删除存储过程及存储函数
DROP PROCEDURE sp_name;
DROP FUNCTION sp_name;
当删除不存在的存储过程或者存储函数的时候,会显示报错:
mysql> DROP PROCEDURE sp_demo1;
ERROR 1305 (42000): PROCEDURE homework.sp_demo1 does not exist
如果想屏蔽错误,以警告的形式提示,可以使用:
DROP PROCEDURE IF EXISTS sp_name;
DROP FUNCTION IF EXISTS sp_name;
例子:
mysql> DROP PROCEDURE IF EXISTS sp_name;
Query OK, 0 rows affected, 1 warning (0.00 sec)
查看警告的内容:SHOW WARNINGS;
mysql> SHOW WARNINGS;
+-------+------+-------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------------------------+
| Note | 1305 | PROCEDURE homework.sp_name does not exist |
+-------+------+-------------------------------------------------------------------------+
1 row in set (0.01 sec)
删除存储过程例子:
mysql> DROP PROCEDURE sp_demo1;
Query OK, 0 rows affected (0.05 sec)
mysql> SHOW CREATE PROCEDURE sp_demo1;
ERROR 1305 (42000): PROCEDURE sp_demo1 does not exist
删除存储函数例子:
DROP FUNCTION username_from_user;
MYSQL存储过程和函数学习笔记的更多相关文章
- MySql存储过程与函数详解
存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MyS ...
- MySQL事务控制语句(学习笔记)
MySQL事务控制语句(学习笔记) MySQL事务控制语句 在mysql命令行的默认下,事务都是自动提交的,sql语句提交后马上会执行commit操作.因此开启一个事务必须使用begi ...
- 《MySQL 存储过程编程》-读书笔记
本书结构: 第一部分:存储编程基础 第1章:存储过程程序基础 第2章:MySQL存储编程指南 第3章:语言基础 第4章:语句块 第5章:在存储程序中使用SQL 第一章:MySQL存储程序介绍 存储程序 ...
- 多IDC数据分布--MySQL多机房部署 - 学习笔记 - 51CTO技术博客
多IDC数据分布--MySQL多机房部署 - 学习笔记 - 51CTO技术博客 多IDC数据分布--MySQL多机房部署
- Paip.断点调试MYSQL存储过程跟函数的解决方案大法
Paip.断点调试MYSQL存储过程跟函数的解决方案大法 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn ...
- Mysql存储过程和函数
Mysql存储过程和函数 基本概念: 创建存储过程和函数是指将经常使用的一组SQL语句的组合在一起,并将这些SQL语句当作一个整体存储在MySQL服务器中.例如,银行经常需要计算用户的利息.不同类别的 ...
- C++学习基础十六-- 函数学习笔记
C++ Primer 第七章-函数学习笔记 一步一个脚印.循序渐进的学习. 一.参数传递 每次调用函数时,都会重新创建函数所有的形参,此时所传递的实参将会初始化对应的形参. 「如果形参是非引用类型,则 ...
- 深挖计算机基础:MySQL实战45讲学习笔记
参考极客时间专栏<MySQL实战45讲>学习笔记 一.基础篇(8讲) MySQL实战45讲学习笔记:第一讲 MySQL实战45讲学习笔记:第二讲 MySQL实战45讲学习笔记:第三讲 My ...
- MySQL实战45讲学习笔记:第三十九讲
一.本节概况 MySQL实战45讲学习笔记:自增主键为什么不是连续的?(第39讲) 在第 4 篇文章中,我们提到过自增主键,由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧 ...
随机推荐
- Python基础----函数
1.作用域: 对于变量的作用域,执行声明并在内存中存在,该变量就可以在下面的代码中使用. if 1==1: name = 'wupeiqi' print name 下面的结论对吗? 外层变量,可以被内 ...
- ShareSDK 社会化分享 集成步骤
第一步 :获取ShareSDK 官网:http://www.mob.com 完整的集成文档:http://wiki.mob.com/android-sharesdk%E5%AE%8C%E6%95%B4 ...
- Dev GridControl 按条件合并相同单元格
Dev 默认的合并方式,只要(垂直方向)相邻两个单元格的值相同都会进行合并,这种方式并不是最优的,所以需要在进行合并的过程中进行判断. 方式如下: 1:先设置需要合并的列为允许合并 OptionsVi ...
- Using Notepad++ to Execute Oracle SQL
原文链接:http://www.toadworld.com/products/toad-for-oracle/b/weblog/archive/2013/08/21/using-notepad-to- ...
- java 代码第一天练习
这个是在其他博文中看到的http://blog.sina.com.cn/eltaera,用来记录学习分享 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个 ...
- C++:MEMSET的大坑三两事
之前写了一题费用流,竟然硬是在写SPFA时为DIS数组赋初始值用了MEMSET数组QAQ 调试了很久也没有弄明白自己是卡在那里了,,,感觉被自己蠢哭了QWQ 错误的姿势!! #include < ...
- 带格式导出数据到Excel
导出按钮事件 protected void Button1_Click(object sender, EventArgs e) { Response.Clear(); ...
- smarty 练习: 分页查询
对查出的数据进行分页,并添加查询 在main.php和main.html两个页面操作: 后台:main.php <?php include("../init.inc.php" ...
- linux 命令行更新sdk
./android list sdk --proxy-host android-mirror.bugly.qq.com --proxy-port 8080 --no-ui -a -s ./androi ...
- SVM及其对偶
引自 http://my.oschina.net/wangguolongnk/blog/111349 1. 支持向量机的目的是什么? 对于用于分类的支持向量机来说,给定一个包含正例和反例(正样本点和负 ...