前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL存储过程

MySQL存储过程

作者头像
恋喵大鲤鱼
发布2018-08-03 14:37:05
11.2K0
发布2018-08-03 14:37:05
举报
文章被收录于专栏:C/C++基础C/C++基础

项目中需要一个脚本,需要在MySQL 中判断表的索引是否存在,不存在则创建。

本以为MySQL存在以下的语句能够完成上面的功能,但是没有。

代码语言:javascript
复制
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 判断表的索引是否存在,不存在则创建的存储过程书写如下。折腾了一个下午,很多细节需要了解,不然会出现自认为莫名其妙的问题。

代码语言:javascript
复制
---------------------------
--@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的判断条件时却出错,目前还不知道原因。

代码语言:javascript
复制
IF NOT EXISTS(show index from tableName where Column_name=idxName)

(4)MySQL(5.1.61)中太苛刻了,竟然不支持在存储过程中有注释,比如下简单的存储过程。

代码语言:javascript
复制
DELIMITER //
CREATE PROCEDURE HelloWorld()
BEGIN 
    SELECT 'Hello World'; 
END// 
DELIMITER ;

执行截图如下:

如果在BEGIN后面加上一行注释就会出现错误。

(5)还有一个很苛刻的地方就是,MySQL的存储过程不能写在同一行。比如将上面的HelloWorld存储过程写在同一行,写成如下格式执行不出错,但也没有成功,此时MySQL的分隔符使我们使用DELIMITER指定的分割符,很是奇怪,有兴趣的读者可以试一下。

代码语言:javascript
复制
DROP PROCEDURE IF EXISTS HelloWorld;  
DELIMITER // CREATE PROCEDURE HelloWorld() BEGIN SELECT 'Hello World'; END// DELIMITER ;

(6)MySQL存储过程declare和set定义变量的区别。

declare定义局部变量:

代码语言:javascript
复制
--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定义变量会话变量:

代码语言:javascript
复制
--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)在存储过程中,使用动态语句,预处理时,动态内容必须赋给一个会话变量。例如:

代码语言:javascript
复制
set @v_sql= sqltext;
PREPARE stmt FROM @v_sql;  
EXECUTE stmt;     
DEALLOCATE PREPARE stmt;

关于存储过程的查看,删除等相关命令,与数据表的操作语句很相似,举例如下:

代码语言:javascript
复制
--查看当前数据库的存储过程
show procedure status;

--查看存储过程创建语句(\G表示以列形式展示结果)
show create procedure [procedureName] \G

--删除存储过程
drop procedure [procedureName];

--如果存在则删除存储过程
drop procedure IF EXISTS [procedureName];

参考文献

[1]MySql中创建存储过程 [2]MySQL存储过程详解 [3]mysql存储过程中 传递表名作参数怎么整

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年07月01日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 参考文献
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档