原文地址: https://blog.csdn.net/H_Rhui/article/details/96920260css
最近看到触发器以后,就想了解一下 存储过程。触发器是一种和表关联的特殊的存储过程。mysql
MySQL 5.0 版本开始支持存储过程。sql
存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。数据库
存储过程是为了完成特定功能的SQL语句集,经编译建立并保存在数据库中,用户可经过指定存储过程的名字并给定参数(须要时)来调用执行。express
存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。编程
声明语句结束符,能够自定义: DELIMITER $$ 或 DELIMITER // 声明存储过程: CREATE PROCEDURE demo_in_parameter(IN p_in int) 存储过程的开始和结束符号: BEGIN …… END 变量赋值: SET @p_in=1 变量定义: DECLARE l_int int unsigned default 5000000; 建立过程体: create function 存储函数名(参数)
存储过程体缓存
BEGIN BEGIN BEGIN statements; END END END
注意:每一个嵌套块及其中的每条语句,必须以分号结束,表示过程体结束的begin-end块(又叫作复合语句compound statement),则不须要分号。安全
为语句块贴标签: 服务器
[begin_label:] BEGIN [statement_list] END [end_label]
例如: 网络
label1: BEGIN label2: BEGIN label3: BEGIN statements; END label3 ; END label2; END label1
MySQL存储过程的参数用在存储过程的定义,共有三种参数类型,IN,OUT,INOUT,形式如:
CREATEPROCEDURE 存储过程名([[IN |OUT |INOUT ] 参数名 数据类型...])
1)in 输入参数
mysql> delimiter $$ mysql> create procedure in_param(in p_in int) -> begin -> select p_in; -> set p_in=2; -> select P_in; -> end$$ mysql> delimiter ; mysql> set @p_in=1; mysql> call in_param(@p_in); +------+ | p_in | +------+ | 1 | +------+ +------+ | P_in | +------+ | 2 | +------+ mysql> select @p_in; +-------+ | @p_in | +-------+ | 1 | +-------+
以上能够看出,p_in 在存储过程当中被修改,但并不影响 @p_id 的值,由于前者为局部变量、后者为全局变量。
使用 Navicat 建立存储过程:
BEGIN SELECT p_in; SET p_in = 2; SELECT p_in; END
2) out输出参数
mysql> delimiter // mysql> create procedure out_param(out p_out int) -> begin -> select p_out; -> set p_out=2; -> select p_out; -> end -> // mysql> delimiter ; mysql> set @p_out=1; mysql> call out_param(@p_out); +-------+ | p_out | +-------+ | NULL | +-------+ #由于out是向调用者输出参数,不接收输入的参数,因此存储过程里的p_out为null +-------+ | p_out | +-------+ | 2 | +-------+ mysql> select @p_out; +--------+ | @p_out | +--------+ | 2 | +--------+ #调用了out_param存储过程,输出参数,改变了p_out变量的值
3) inout 输入参数
mysql> delimiter $$ mysql> create procedure inout_param(inout p_inout int) -> begin -> select p_inout; -> set p_inout=2; -> select p_inout; -> end -> $$ mysql> delimiter ; mysql> set @p_inout=1; mysql> call inout_param(@p_inout); +---------+ | p_inout | +---------+ | 1 | +---------+ +---------+ | p_inout | +---------+ | 2 | +---------+ mysql> select @p_inout; +----------+ | @p_inout | +----------+ | 2 | +----------+ #调用了inout_param存储过程,接受了输入的参数,也输出参数,改变了变量
注意:
一、若是过程没有参数,也必须在过程名后面写上小括号例:
CREATE PROCEDURE sp_name ([proc_parameter[,...]]) ……
二、确保参数的名字不等于列的名字,不然在过程体中,参数名被当作列名来处理
建议:
1) 变量定义
局部变量声明必定要放在存储过程体的开始:
datatype 为 MySQL 的数据类型,如: int, float, date,varchar(length)
DECLARE variable_name [,variable_name...] datatype [DEFAULT value];
例如:
DECLARE l_int int unsigned default 4000000; DECLARE l_numeric number(8,2) DEFAULT 9.95; DECLARE l_date date DEFAULT '1999-12-31'; DECLARE l_datetime datetime DEFAULT '1999-12-31 23:59:59'; DECLARE l_varchar varchar(255) DEFAULT 'This will not be padded';
2)变量赋值
SET 变量名 = 表达式值 [,variable_name = expression ...]
3)用户变量
在MySQL客户端使用用户变量:
mysql > SELECT 'Hello World' into @x; mysql > SELECT @x; +-------------+ | @x | +-------------+ | Hello World | +-------------+ mysql > SET @y='Goodbye Cruel World'; mysql > SELECT @y; +---------------------+ | @y | +---------------------+ | Goodbye Cruel World | +---------------------+ mysql > SET @z=1+2+3; mysql > SELECT @z; +------+ | @z | +------+ | 6 | +------+
在存储过程当中使用用户变量
CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World'); SET @greeting='Hello'; CALL GreetWorld( ); -- 输出: hello World
在存储过程间传递全局范围的用户变量
CREATE PROCEDURE p1() SET @last_procedure='p1'; CREATE PROCEDURE p2() SELECT CONCAT('Last procedure was ',@last_procedure); CALL p1(); CALL p2(); -- 输出 Last procedure was p1
注意:
-- 查询存储过程 show procedure status where db='test'; -- 删除存储过程 DROP PROCEDURE p1; DROP PROCEDURE p2;
1) 变量做用域
DELIMITER // CREATE PROCEDURE proc3() BEGIN declare x1 varchar(5) default 'outer'; BEGIN DECLARE x1 VARCHAR (5) DEFAULT 'inner' ; SELECT x1 ; END; SELECT x1 ; END;// DELIMITER ; CALL proc3(); -- 输出 inner -- 输出 outer
2). 条件语句
-- 建立表用来测试 CREATE TABLE `t` ( `s` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- 初始化一条数据 INSERT INTO `test`.`t` (`s`) VALUES (0); DELIMITER // CREATE PROCEDURE proc2(IN parameter int) BEGIN declare var int; set var=parameter+1; if var=0 THEN INSERT INTO t VALUES(1); end if; if parameter=0 then update t set s=s+1; else update t set s=s+2; end if; END;// DELIMITER ; // 调用存储过程 CALL proc2(1); // 删除存储过程 drop PROCEDURE proc2;
查询是否开启了慢查询:
show variables like '%slow%'; -- Mysql 默认是关闭的
-- 开启慢查询 set global slow_query_log=1; -- 查看统计的时长 show variables like 'long_query_time'; --修改统计的时长为一秒。 请注意,修改以后,当前会话无效,从新链接以后能够看到修改效果 set global long_query_time=1;
-- 查看当前安装的数据库 支持哪些 引擎 show engines; -- 查看当前数据库使用的哪一种引擎 SHOW VARIABLES LIKE 'storage_engine';
经常使用的存储引擎 :Myisam innodb(目前应该是默认使用 innodb) memory
Myisam 存储引擎:MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其余应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事物。
Innodb 存储引擎:InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键
Memory :MEMORY存储引擎将表中的数据存储到内存中,当咱们的数据频繁变化的时候,并且不须要入库,这个时候用memory存储引擎。
优化小技巧
1. 对查询进行优化,要尽可能避免全表扫描,首先应考虑在 where 及 order by 涉及的列上创建索引。2. 应尽可能避免在 where 子句中对字段进行 null 值判断,不然将致使引擎放弃使用索引而进行全表扫描3. 应尽可能避免在 where 子句中使用 != 或 <> 操做符,不然将引擎放弃使用索引而进行全表扫描。4. 应尽可能避免在 where 子句中使用 or 来链接条件,若是一个字段有索引,一个字段没有索引,将致使引擎放弃使用索引而进行全表扫描,如select id from t where num=10 or Name = 'admin'能够这样查询:select id from t where num = 10 union all select id from t where Name = 'admin'5. select count(*) from table;这样不带任何条件的count会引发全表扫描,而且没有任何业务意义,是必定要杜绝的。调优参数:6. back_log:back_log值指出在MySQL暂时中止回答新请求以前的短期内多少个请求能够被存在堆栈中。也就是说,若是MySql的链接数据达到max_connections时,新来的请求将会被存在堆栈中,以等待某一链接释放资源,该堆栈的数量即back_log,若是等待链接的数量超过back_log,将不被授予链接资源。7. wait_timeout:数据库链接闲置时间,闲置链接会占用内存资源。8. max_user_connection: 最大链接数,默认为0无上限,最好设一个合理上限9. thread_concurrency:并发线程数,设为CPU核数的两倍10. skip_name_resolve:禁止对外部链接进行DNS解析,消除DNS解析时间,但须要全部远程主机用IP访问11. key_buffer_size:索引块的缓存大小,增长会提高索引处理速度,对MyISAM表性能影响最大。对于内存4G左右,可设为256M或384M,经过查询show status like 'key_read%',保证key_reads / key_read_requests在0.1%如下最好12. innodb_buffer_pool_size:缓存数据块和索引块,对InnoDB表性能影响最大。经过查询show status like 'Innodb_buffer_pool_read%',保证(Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests越高越好13. innodb_additional_mem_pool_size:InnoDB存储引擎用来存放数据字典信息以及一些内部数据结构的内存空间大小,当数据库对象很是多的时候,适当调整该参数的大小以确保全部数据都能存放在内存中提升访问效率,当太小的时候,MySQL会记录Warning信息到数据库的错误日志中,这时就须要该调整这个参数大小14. innodb_log_buffer_size:InnoDB存储引擎的事务日志所使用的缓冲区,通常来讲不建议超过32MB15. query_cache_size:缓存MySQL中的ResultSet,也就是一条SQL语执行的结果集,因此仅仅只能针对select语句。当某个表的数据有任何任何变化,都会致使全部引用了该表的select语句在Query Cache中的缓存数据失效。因此,当咱们的数据变化很是频繁的状况下,使用Query Cache可能会得不偿失。根据命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))进行调整,通常不建议太大,256MB可能已经差很少了,大型的配置型静态数据可适当调大.能够经过命令show status like 'Qcache_%'查看目前系统Query catch使用大小16. read_buffer_size:MySql读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySql会为它分配一段内存缓冲区。若是对表的顺序扫描请求很是频繁,能够经过增长该变量值以及内存缓冲区大小提升其性能17. sort_buffer_size:MySql执行排序使用的缓冲大小。若是想要增长ORDER BY的速度,首先看是否可让MySQL使用索引而不是额外的排序阶段。若是不能,能够尝试增长sort_buffer_size变量的大小18. read_rnd_buffer_size:MySql的随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySql会首先扫描一遍该缓冲,以免磁盘搜索,提升查询速度,若是须要排序大量数据,可适当调高该值。但MySql会为每一个客户链接发放该缓冲空间,因此应尽可能适当设置该值,以免内存开销过大。19. record_buffer:每一个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。若是你作不少顺序扫描,可能想要增长该值20. thread_cache_size:保存当前没有与链接关联可是准备为后面新的链接服务的线程,能够快速响应链接的线程请求而无需建立新的21. table_cache:相似于thread_cache_size,但用来缓存表文件,对InnoDB效果不大,主要用于MyISAM