最近在做一个移动设备多类型登录的统一用户系统。其中记录用户资料的部分,因为涉及到更换设备的相同用户、同一个用户多类型同时具备的情况,所以想分辨出尽量少的用户去合理记录,就需要多次查询。于是决定研究一下 MySQL 存储程序。

  MySQL 现在是 5.5 或者 5.6 。因为存储程序是 5.x 才具备的特性,所以放弃了具有中文文档的 5.1 ,选择可能会修改了很多问题的 5.5 。可惜这就造成我不得不去看在线英文文档,因为我实在找不到 MySQL 5.5 的 PDF 版中文文档…… 在线文档地址是:http://dev.mysql.com/doc/refman/5.5/en/index.html ,其首页有内容表格,里边有“视图和存储程序”这一项,也就是第 19 章。

MySQL 中,会出现 Stored Programs 这个词。但实际上它是存储的程序之意思,包括存储程序和触发程序。存储程序是 Stored Routines ,跟 Oracle 一样,包括过程体(Procedures)和函数体(Functions)。过程体通过指定输出类型参数将过程值带出,用 CALL 语句加过程名和参数进行调用;函数体具有返回值,直接用函数名和参数调用。

声明过程体请先参看我的例子。首先我为了记录用户登录数据,制作了这个表(涉及公司机密的有关名称已经更改):

DROP TABLE IF EXISTS test.MyTable;
CREATE TABLE test.MyTable
(
id INTEGER,
type VARCHAR(16),
name VARCHAR(16),
passwd VARCHAR(16),
updateTime DATETIME,
deviceMacs VARCHAR(255),
CONSTRAINT test_MyTable_pk PRIMARY KEY (id, type)
);

通过 id 作为用户的唯一标识。然后编写了如下的存储过程(涉及公司机密的有关名称已经更改):

DROP PROCEDURE IF EXISTS test.myProcedure;
DELIMITER //
CREATE PROCEDURE test.myProcedure
(
IN vType VARCHAR(16),
IN vName VARCHAR(16),
IN vPasswd VARCHAR(16),
IN vDeviceMac VARCHAR(12),
OUT iId INTEGER
) SQL SECURITY INVOKER
/* ********** ********** ********** **********
This is a database procedure for user login process.
author:Shane Loo Li
version:1.1.0, 2012-7-6 FridayNew
history:1.1.0, 2012-7-6 FridayShane Loo LiNew
********** ********** ********** ********** */
BEGIN
DECLARE iCount INTEGER;
DECLARE vDeviceMacs VARCHAR(255);
SELECT COUNT(1) INTO iCount FROM test.MyTable
WHERE type = vType AND name = vName;
-- 如果不存在传入的用户,则插入新登录信息。
IF iCount = 0 THEN
SELECT COUNT(1) INTO iCount FROM test.MyTable
WHERE deviceMac LIKE CONCAT('%', vDeviceMac, '%');
IF iCount = 0 THEN
INSERT INTO test.MyTable VALUES (
(SELECT MAX(id) + 1 FROM test.MyTable),
vType, vName, vPasswd, NOW(), vDeviceMac);
ELSE
SELECT COUNT(1) INTO iCount FROM test.MyTable
WHERE deviceMac LIKE CONCAT('%', vDeviceMac, '%')
AND type = vType;
IF iCount = 0 THEN
SELECT id INTO iId FROM test.MyTable
WHERE deviceMac LIKE CONCAT('%', vDeviceMac, '%')
AND type = vType LIMIT 1;
INSERT INTO test.MyTable VALUES (
iId, vType, vName, vPasswd, NOW(), vDeviceMac);
ELSE
INSERT INTO test.MyTable VALUES (
(SELECT MAX(id) + 1 FROM test.MyTable),
vType, vName, vPasswd, NOW(), vDeviceMac);
END IF;
END IF;
-- 如果存在传入的用户,则更新其记录
ELSE
SELECT id, deviceMacs INTO iId, vDeviceMacs FROM test.MyTable
WHERE type = vType AND name = vName LIMIT 1;
IF vDeviceMacs LIKE CONCAT('%', vDeviceMac, '%') THEN
UPDATE test.MyTable SET passwd=vPasswd, updateTime=NOW()
WHERE id = iId AND type = vType AND name = vName;
ELSE
UPDATE test.MyTable SET passwd=vPasswd, updateTime=NOW(),
deviceMacs=CONCAT(vDeviceMacs, ',', vDeviceMac)
WHERE id = iId AND type = vType AND name = vName;
END IF;
END IF;
END
//
DELIMITER ;

这里对代码进行一些解释。
1、DELIMITER 是 MySQL 用来声明语句终止符的关键字。由于存储程序之中会包含很多默认的终止符分号,所以在声明存储程序之前,需要将终止符改变成其它的。我使用的是 // ,这也是 MySQL 官方文档示例中使用的。
2、参数的输入输出类型在参数名前边。这和 Oracle 不同。
3、MySQL 存储程序中变量类型的 VARCHAR 必须指定长度,这和 Oracle 有所不同。
4、程序内部的本地变量用 DECLARE 关键字声明。
5、SQL SECURITY INVOKER 的意思是,由执行者进行执行权限确认。执行者需要对这个存储程序所在的库具有 EXECUTE 权限。
这意味着,GRANT 权限时候,如果想使用存储程序,就不能再只赋予 SELECT, INSERT, UPDATE, DELETE 了,还需要增加 EXECUTE 。
6、注释有二种方式,分别是 -- 的单行注释,和 /*  */ 的多行注释。这和 Oracle 一样。
所有的这些声明语句内容,都可以参看 http://dev.mysql.com/doc/refman/5.5/en/create-procedure.html 。

可以通过 mysql.proc 表来查询已有存储过程的信息,常用字段为 db 和 name ,表示存储过程的数据库和名称。
这里需要注意的是,不但程序员需要查询 mysql.proc 表,执行存储过程的时候,数据库执行用户也需要能够查询 mysql.proc 表。如果执行者没有对 mysql.proc 的 SELECT 权限,则存储过程执行时会产生错误:
java.sql.SQLException: User does not have access to metadata required to determine stored procedure parameter types. If rights can not be granted, configure connection with "noAccessToProcedureBodies=true" to have driver generate parameters that represent INOUT strings irregardless of actual parameter types.
提供一个增加权限的语句参考:

GRANT SELECT ON mysql.proc TO username@'192.168.0%';
FLUSH PRIVILEGES;

接下来说一说通过 Java 程序调用 MySQL 存储程序的方法。
MySQL 存储程序基本遵循了 SQL 标准,于是只要不涉及 MySQL 特性的存储程序,我们也就可以使用标准的 java.sql 包里边关于存储程序的各种类来实现调用。
1、获取 Connection 对象
2、通过 Connection 的 prepareCall() 方法,生成 CallableStatement 对象。
3、通过 setInt(), setString() 一类的方法注册输入参数;通过 registerOutParameter() 注册输出参数。
4、用 execute() 方法执行语句。
5、通过 getInt(), getString() 一类的方法获取输出参数的值。
以下是我调用 MySQL 存储过程的一段示例程序。其中获取 Connection 对象的方法,是来自于自己做的连接池。

Connection conn = (Connection) line.use();
CallableStatement cs = null;
int result = -1;
try
{
cs = conn.prepareCall("{call amdream.testProcedure(?, ?)}");
cs.setInt(1, 1099);
cs.registerOutParameter(2, Types.INTEGER);
cs.execute();
result = cs.getInt(2);
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
try { conn.close(); } catch (Exception ex) { }
}

用 Java 调用存储程序会有一定时间的延时。所以如果存储程序内容密度不是很大,请考虑在实际环境中测试耗时,以决定使用存储程序还是多次执行 SQL 语句。

MySQL 存储过程初研究相关推荐

  1. mysql 存储过程 控制台_mysql 存储过程 调试

    mysql存储过程之游标遍历数据表 原文:mysql存储过程之游标遍历数据表 今天写一个mysql存储过程,根据自己的需求要遍历一个数据表,因为对存储过程用的不多,语法不甚熟悉,加之存储过程没有调试环 ...

  2. mysql数据库存储数据的过程_[数据库]MySql存储过程总结

    [数据库]MySql存储过程总结 0 2014-06-12 01:00:50 之前总是在MSSQL上写存储过程,没有在MYSQL上写过,也基本没有用过,今天需要用到MYSQL,研究了下,把项目的需要的 ...

  3. mysql存储过程into_MySQL存储过程中使用SELECT …INTO语句为变量赋值

    使用SELECT -INTO语句为变量赋值 在MySQL存储过程中,可以使用SELECT -INTO语句对变量进行赋值,该语句在数据库中进行查询,并将得到的结果赋值给变量.SELECT -INTO语句 ...

  4. mysql存储过程语法 if_mysql存储过程语法 if

    MySql存储过程 MySQL 存储过程是从 MySQL 5.0 开始增加的新功能.存储过程的优点有一箩筐.不过最主要的还是执行效率和SQL 代码封装.特别是 SQL 代码封装功能,如果没有存储过程, ...

  5. MySQL 存储过程的写法

    最近因为公司需要做将Oracle 转换为MySQL,其中包含存储过程,所以就对MySQL存储过程的写法做了一些研究. DROP PROCEDURE IF EXISTS ch_passw;   CREA ...

  6. MySQL数据库初体验

    文章目录 一.MySQL数据库初体验 1.数据库的基本概念 2.数据库系统发展史 2.1文件管理系统的缺点 2.2数据库系统发展阶段 3.数据库原理 3.1数据的时代 3.2数据的分类 3.3DBMS ...

  7. mysql存储过程 limit_mysql存储过程 limit

    SQL分页查询代码 SQL Server 关于分页 SQL 的资料许多,有的使用存储过程,有的使用游标.本人不喜欢使用游标,我觉得它耗资.效率低:使用存储过程是个不错的选择,因为存储过程是颠末预编译的 ...

  8. mysql 存储过程 replace_mysql 存储过程 create or replace

    MySQL和Oracle对比之存储过程 昨天晚上帮一个朋友处理了一个关于存储过程的问题,他需要迁移一些Oracle中的存储过程到MySQL中来,但是改了一部分的程序,发现MySQL中没法编译了,报了很 ...

  9. 常用MySQL函数存储过程_解析MySQL存储过程、常用函数代码

    mysql存储过程的概念: 存储在数据库当中可以执行特定工作(查询和更新)的一组SQL代码的程序段. mysql函数的概念: 函数是完成特定功能的SQL语句,函数分为内置函数和自定义函数(user-d ...

最新文章

  1. Linux下修改PATH环境变量
  2. 直线宽度2 points wide_OpenGL 绘图实例二之直线和圆弧的绘制
  3. Spring.net 模块组成
  4. 【控制】《多智能体系统一致性与复杂网络同步控制》郭凌老师-第1章-绪论
  5. 从互联网的旁观者,转为互联网的建设者,推动者!!!
  6. linux获取性能指数,Linux环境获取系统性能数据
  7. [转]nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件
  8. java 打包后 文件资源文件 jar,JAVA打包成JAR无法找到资源文件
  9. MONO,原来你是水中月
  10. XproerIM-V1,2,12,65475发布。
  11. 数据存储的问题(1)
  12. 艾伟也谈项目管理,开始一个项目时最重要的是什么?
  13. 中望cad自定义快捷键命令_中望CAD快捷键全集
  14. 添加打印机计算机无法访问,Win7系统添加打印机提示Windows无法打开“添加打印机”的解决方法...
  15. vulnhub Photographer: 1
  16. python设置文件权限_python通用权限框架
  17. [h5py] 解决ImportError: libhdf5.so.103: cannot open shared object file: No such file or directory
  18. 九月的诗11首-光剑
  19. android listview 导航条,Android侧边导航栏+ListView基础实践
  20. 如何从Confluence数据库手动删除陈旧草稿

热门文章

  1. 求单独出现的数,冒泡排序优化,strncpy的优化
  2. 1.1 《硬啃设计模式》 第1章 大话设计模式
  3. 使用思科3640实现不同网段通讯
  4. 建立普通用户信任关系,
  5. VS.net 2005 试用(1)
  6. MnasNet:迈向移动端机器学习模型设计的自动化之路
  7. [转] 电子技术·笔记1(9月份)
  8. 多项物联网技术评为即将改变世界的革新技术
  9. 在博客园添加Lisp(或其它)代码高亮
  10. 转载几个和职业建议相关的文章