MySQL存储过程
2016-07-01 19:28
721 查看
项目中需要一个脚本,需要在MySQL 中判断表的索引是否存在,不存在则创建。
本以为MySQL存在以下的语句能够完成上面的功能,但是没有。
可惜啊!MySQL目前并不支持在SQL语句中存在流控制语句,例如上面的
MySQL 判断表的索引是否存在,不存在则创建的存储过程书写如下。折腾了一个下午,很多细节需要了解,不然会出现自认为莫名其妙的问题。
阅读上面的代码需要注意如下几个问题。
(1)MySQL存储过程中是不支持表名和列名作为变量。如果表名和列名作为参数的话,只有通过concat拼接动态sql字符串,交由prepare预处理后,再由execute来执行。但是在IF EXISTS或者IF NOT EXISTS中sql语句作为条件出现时,表名和列名可以作为变量。
感觉MySQL功能还是不够强大啊,功能上有诸多的限制和约束!唉,谁叫它是开源免费的呢!个人体会,也可能是我对MySQL还不够了解!
(2)DELIMITER $用于改变MySQL的分隔符,否则MySQL在回车的情况下会按照默认分割符分号;将存储过程拆分,使其执行失败。存储过程结束后,使用
(3)本来以为可以使用如下语句来判断某个表的指定索引是否存在,但作为IF NOT EXISTS的判断条件时却出错,目前还不知道原因。
(4)MySQL(5.1.61)中太苛刻了,竟然不支持在存储过程中有注释,比如下简单的存储过程。
执行截图如下:
如果在BEGIN后面加上一行注释就会出现错误。
(5)还有一个很苛刻的地方就是,MySQL的存储过程不能写在同一行。比如将上面的HelloWorld存储过程写在同一行,写成如下格式执行不出错,但也没有成功,此时MySQL的分隔符使我们使用DELIMITER指定的分割符,很是奇怪,有兴趣的读者可以试一下。
(6)MySQL存储过程declare和set定义变量的区别。
declare定义局部变量:
set定义变量会话变量:
说到变量,必然要讨论变量的作用域和生命周期。二者的区别主要有:
(1)作用域和生命周期的区别。 declare定义局部变量,作用域和生命周期在当前存储过程中有效。set定义会话变量(session variable),也叫做用户定义的变量(user defined variable)。作用域为当前存储过程,生命周期为当前会话(就是某个应用的一个连接过程)。这种变量要在变量名称前面加上“@”符号,这个变量可以在被调用的存储过程或者代码之间共享数据,有点像CC++中的局部static变量。具体例子可参考: MySQL存储过程——变量。
(2) set定义会话变量的时候,必须显示指明变量的初值,且以@开头。declare定义局部变量时无需显示指明变量的初值,后面可由set和select into进行赋值。
(3) set @不需要声明类型,declare必须指定类型。
(4)在存储过程中,使用动态语句,预处理时,动态内容必须赋给一个会话变量。例如:
关于存储过程的查看,删除等相关命令,与数据表的操作语句很相似,举例如下:
[2]MySQL存储过程详解
[3]mysql存储过程中 传递表名作参数怎么整
本以为MySQL存在以下的语句能够完成上面的功能,但是没有。
IF NOT EXISTS(show index from [tableName]) THEN alter table [tableName] add index([collumName]) END IF; --或者 create index [index_name] on [table_name] ([column_list]) IF NOT EXISTS([index_name]) ;
可惜啊!MySQL目前并不支持在SQL语句中存在流控制语句,例如上面的
IF NOT EXISTS THEN END IF;让人痛心疾首。但是我们可以使用存储过程完成上面要求的功能。
MySQL 判断表的索引是否存在,不存在则创建的存储过程书写如下。折腾了一个下午,很多细节需要了解,不然会出现自认为莫名其妙的问题。
--------------------------- --@brief:判断指定数据表的索引是否存在,如果不存在则创建 --@param:tableName:数据表名称;idxName:索引名称;columnName:建立索引的列名称 --------------------------- DROP PROCEDURE IF EXISTS pro_addIndex; DELIMITER $ create procedure pro_addIndex(IN tableName VARCHAR(64),IN idxName VARCHAR(200),IN columnName VARCHAR(64)) begin IF NOT EXISTS (SELECT * FROM information_schema.statistics WHERE table_schema="databaseName" AND table_name=tableName AND index_name=idxName) THEN SET @sqlStr=CONCAT("alter table ",tableName," add index(",columnName,")"); prepare sqlStatement from @sqlStr; EXECUTE sqlStatement; deallocate prepare sqlStatement; end if; end$ DELIMITER ; ---调用存储过程 call [procedureName]([para1],[para2],...);
阅读上面的代码需要注意如下几个问题。
(1)MySQL存储过程中是不支持表名和列名作为变量。如果表名和列名作为参数的话,只有通过concat拼接动态sql字符串,交由prepare预处理后,再由execute来执行。但是在IF EXISTS或者IF NOT EXISTS中sql语句作为条件出现时,表名和列名可以作为变量。
感觉MySQL功能还是不够强大啊,功能上有诸多的限制和约束!唉,谁叫它是开源免费的呢!个人体会,也可能是我对MySQL还不够了解!
(2)DELIMITER $用于改变MySQL的分隔符,否则MySQL在回车的情况下会按照默认分割符分号;将存储过程拆分,使其执行失败。存储过程结束后,使用
DELIMITER ;来恢复MySQL的分割符,注意DELIMITER和;之间要有空格。
(3)本来以为可以使用如下语句来判断某个表的指定索引是否存在,但作为IF NOT EXISTS的判断条件时却出错,目前还不知道原因。
IF NOT EXISTS(show index from tableName where Column_name=idxName)
(4)MySQL(5.1.61)中太苛刻了,竟然不支持在存储过程中有注释,比如下简单的存储过程。
DELIMITER // CREATE PROCEDURE HelloWorld() BEGIN SELECT 'Hello World'; END// DELIMITER ;
执行截图如下:
如果在BEGIN后面加上一行注释就会出现错误。
(5)还有一个很苛刻的地方就是,MySQL的存储过程不能写在同一行。比如将上面的HelloWorld存储过程写在同一行,写成如下格式执行不出错,但也没有成功,此时MySQL的分隔符使我们使用DELIMITER指定的分割符,很是奇怪,有兴趣的读者可以试一下。
DROP PROCEDURE IF EXISTS HelloWorld; DELIMITER // CREATE PROCEDURE HelloWorld() BEGIN SELECT 'Hello World'; END// DELIMITER ;
(6)MySQL存储过程declare和set定义变量的区别。
declare定义局部变量:
--declare定义变量 DECLARE [variable_name] [datatype(size)] DEFAULT [default_value]; --例如 DECLARE count int DEFAULT 0; --使用set赋值 set count=5; --还可以通过SELECT INTO语句将返回的值赋给变量 SELECT COUNT(*) INTO count FROM [tableName]; --可同时定义多个变量 DECLARE x, y INT DEFAULT 0
set定义变量会话变量:
--set定义变量 set @count=5;
说到变量,必然要讨论变量的作用域和生命周期。二者的区别主要有:
(1)作用域和生命周期的区别。 declare定义局部变量,作用域和生命周期在当前存储过程中有效。set定义会话变量(session variable),也叫做用户定义的变量(user defined variable)。作用域为当前存储过程,生命周期为当前会话(就是某个应用的一个连接过程)。这种变量要在变量名称前面加上“@”符号,这个变量可以在被调用的存储过程或者代码之间共享数据,有点像CC++中的局部static变量。具体例子可参考: MySQL存储过程——变量。
(2) set定义会话变量的时候,必须显示指明变量的初值,且以@开头。declare定义局部变量时无需显示指明变量的初值,后面可由set和select into进行赋值。
(3) set @不需要声明类型,declare必须指定类型。
(4)在存储过程中,使用动态语句,预处理时,动态内容必须赋给一个会话变量。例如:
set @v_sql= sqltext; PREPARE stmt FROM @v_sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
关于存储过程的查看,删除等相关命令,与数据表的操作语句很相似,举例如下:
--查看当前数据库的存储过程 show procedure status; --查看存储过程创建语句(\G表示以列形式展示结果) show create procedure [procedureName] \G --删除存储过程 drop procedure [procedureName]; --如果存在则删除存储过程 drop procedure IF EXISTS [procedureName];
参考文献
[1]MySql中创建存储过程[2]MySQL存储过程详解
[3]mysql存储过程中 传递表名作参数怎么整
相关文章推荐
- MySQL存储过程
- 教务系统——mysql课程设计
- 如何从MySQL官方Yum仓库安装MySQL5.6
- 多实例mysql数据库安装详解
- [已解决]EnvironmentError: mysql_config not found
- mysql事务(2)
- MySQL 多实例详解
- MySQL 多实例详解
- Mysql错误处理
- Mysql显示行号
- 一些常用数据库操作在mysql及sql server中实现方式的差异
- Highstock+flask+mysql实现多线条动态刷新
- mysql之经典case when
- mysql-5.7.13-winx64解压版配置安装小结
- mysql 游标类型
- Mysql编码引起的Illegal mix of collations
- MYSQL随机取出20条数据
- mysql 5.7.13 winx32 安装步骤
- MYSQL嵌套查询
- mysql 视图创建及使用