`
Surmounting
  • 浏览: 67852 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MySQL 存储过程初研究

阅读更多

最近在做一个移动设备多类型登录的统一用户系统。其中记录用户资料的部分,因为涉及到更换设备的相同用户、同一个用户多类型同时具备的情况,所以想分辨出尽量少的用户去合理记录,就需要多次查询。于是决定研究一下 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 Friday	New
history:	1.1.0, 2012-7-6 Friday	Shane Loo Li	New
********** ********** ********** ********** */
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 语句。

1
0
分享到:
评论

相关推荐

    mysql3.5版本

    MySQL 3.5 版本是数据库管理系统 MySQL 的一个早期版本,它在20世纪90年代末到21世纪初被广泛使用。这个版本在当时因其高效、稳定和开源特性而备受青睐,尤其对于小型企业和个人开发者来说,MySQL 3.5 提供了一个...

    精通PHP+MySQL应用开发书中源码

    书中源码涵盖了数据库设计、SQL查询、事务处理、存储过程、触发器等内容,这些都是构建高效数据库应用的关键技术。 在提供的压缩包文件中,可以看到一系列以"C"命名的文件或目录,这些很可能是按照书中的章节进行...

    2016年1月整理的全国邮编excel及mysql

    5. **数据导入与导出**:从Excel到MySQL的数据迁移过程涉及数据导入和导出技术,如使用MySQL命令行工具或者可视化工具(如MySQL Workbench)来执行SQL脚本。 6. **数据安全与隐私**:尽管邮编本身不涉及个人隐私,...

    基于ssm+mysql智能图书馆导航系统源码数据库.doc

    主要内容包括研究背景、技术栈介绍(SSM框架、MySQL技术等)、系统设计原理及其实现过程中的关键技术点。 ### 研究背景 当前,随着信息技术的飞速发展,人们对于图书馆服务的需求也越来越高。传统图书馆往往存在着...

    基于Java的超市管理系统源码,数据库MySQL(附加论文13000字)

    这是一个关于使用Java编程语言开发的超市管理系统的项目,结合了MySQL数据库进行数据存储与管理。这个项目不仅提供了源代码,还包含了一个详细的46页论文,论文字数超过13000字,深入探讨了系统的设计、实现和功能。...

    基于ssm+mysql的课程进度管理系统源码论文.doc

    《基于SSM+MySQL的课程进度管理系统的设计与实现...综上所述,基于SSM+MySQL的课程进度管理系统旨在通过现代信息技术,优化教学过程,提升教学效率,实现教育资源的共享与优化配置,对提高教学质量具有积极的推动作用。

    研究报告:实时架构演进.pdf

    2. 数据存储:采用了RedisCluster进行缓存,同时利用Hbase和MySQL存储大量历史数据。随着业务发展,Redis采用了双写策略,保证高可用性,而Hbase则用于处理大规模非结构化数据。 3. 监控:在高速发展阶段,监控体系...

    Mysql源码学习笔记 偷窥线程

    这两个函数分别位于`mysys`项目和`innobase`项目下,揭示了MySQL的存储引擎插件化设计。`innobase`实际上是InnoDB存储引擎的实现,它有自己的线程管理封装。这种插件化设计使得MySQL能适应各种应用场景,用户可以...

    《数字传媒研究》编辑部管理系统的设计与实现.pdf

    稿件在上传、存储、传递的全过程中都得到了加密处理,确保稿件内容的机密性和完整性。而系统的权限管理机制还为不同级别的编辑人员设置了不同的访问权限,既满足了工作需求,又保证了稿件管理的安全性。 综上所述,...

    复杂属性环境下NoSQL分布式大数据挖掘方法研究.pdf

    研究表明,与传统的RDBMS或其他NoSQL数据库(如MYSQL)以及贝叶斯模型等方法相比,该方法在挖掘准确性、稳定性和实用性方面都有显著提升。这一进步为复杂属性环境下的大数据处理开辟了新的可能,特别是在实时分析、...

    基于jsp的自然灾害论坛源码数据库论文.doc

    【基于jsp的自然灾害论坛源码...总的来说,该论文详细解析了基于JSP的自然灾害论坛的开发过程,涵盖了从需求分析、数据库设计到系统实现的各个环节,是学习和研究Web开发,尤其是JSP和MySQL结合应用的一个典型示例。

    基于微信小程序的快递系统开题报告.docx

    系统采用的技术包括Node.js作为后端开发框架,MySQL作为数据库存储,确保了系统的稳定性和实用性。 3. 设计的基本内容与拟解决的主要问题: 3.1 基本内容 3.1.1 需求分析 系统设计之初,进行了全面的需求分析,...

    基于Java技术的校园二手市场交易平台系统开题报告

    采用Java编程语言进行系统开发,结合Spring Boot框架实现后端服务,使用MySQL数据库存储数据,前端界面则可以采用React或Vue.js等现代Web框架。同时,利用安全技术,如HTTPS、JWT等,保障交易安全。 三、研究条件和...

    2017224403-于丽蔷-毕业论文-初版1

    在技术实现上,论文采用了MySQL数据库作为数据存储的基石,并利用SpringBoot和Vue.js构建了一个B/S架构的系统。这样的组合不仅保证了系统的稳定性和安全性,也使得系统的操作更加简便快捷。系统被划分为用户管理、...

    Structured Query Language的缩写

    它由IBM的研究员在20世纪70年代初开发,初衷是为了操作当时新兴的关系数据库模型。SQL的设计目标是让用户能以简洁的、标准化的方式来检索、更新和管理存储在数据库中的数据。 SQL的核心功能主要包括以下几点: 1. ...

    基于SpringBoot论坛网站系统论文.doc

    - **数据库层**:使用MySQL数据库存储各类数据,包括用户信息、帖子内容、评论等。 #### 功能设计 本论坛网站设计了丰富的功能模块,以满足不同用户的需求: - **用户注册与登录**:用户可以通过邮箱或手机号进行...

    答辩ppt336水果销售管理网站.pptx

    经过设计和实现阶段的精心工作,本文的结论及研究成果如下:成功构建了一个结合Java和Mysql的水果销售管理网站。网站具有响应式设计,能够适应不同设备的访问,提升用户体验。随着本项目的完成,商家和消费者都能够...

Global site tag (gtag.js) - Google Analytics