一、mysql数据库存储过程:
1、什么是存储过程
存储过程(英文:stored procedure)是在大型数据库系统中,为了完成特定功能而编写的一组的sql语句集。存储过程经编译存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
2、与一般sql语句相比,使用存储过程有哪些优点,有哪些缺点
优点:
1)、减少了脚本的执行环节,缩短了获取数据的时间。存储过程只在创建的时进行编译,在调用使用的时候直接执行,不需再次编译;而一般sql语句每次执行前都需要编译一次,故效率没有存储过程高;
2)、减少网络传输量,提高了传输速度。存储过程编译后存储在数据库服务器上,使用的时候只需要指定存储过程的名字并给出参数(如果该存储过程带有参数)就可以了;而一般sql语句需要将所执行语句字符串传输到数据库服务器端,相比于存储过程而言向数据库服务端传送的字符串长度比较大;
3)、安全性比较高。为存储过程参数赋值只能使用问号传参的形式(这一点可以通过下面jdbc对mysql数据库存储过程的调用例子体现出来),这样可以防止sql注入式攻击;一般sql语句也可以做到防止sql注入式攻击,但是并不是必须的。可以将grant、deny以及revoke权限应用于存储过程,即言可以设定只有某些用户才具有对指定存储过程的使用权;
缺点:
1)、如果在一个程序系统中大量的使用存储过程,当程序交付使用的时候随着客户需求的增加会导致数据结构的变化,接着就是存储过程的修改,这样系统维护就会越来越难并且代价也会越来越大。
3、怎样创建存储过程及创建存储过程需要注意的地方
存储过程的创建格式为:
create procedure 存储过程名([[in |out |inout ] 参数名 数据类形...])
begin
存储过程体
end
创建存储过程的具体例子见下面jdbc对mysql数据库存储过程的调用例子;
需要注意的地方:见下面jdbc对mysql数据库存储过程的调用例子内创建存储过程语句中的注释;
二、jdbc对mysql数据库存储过程的调用:
为了更加直观的介绍jdbc如何实现对mysql数据库存储过程的调用,这里直接以例子的形式展示。
1、没有任何输入和输出参数的存储过程
package com.ghj.packageoftest;import java.sql.callablestatement;import java.sql.connection;import java.sql.resultset;import java.sql.sqlexception;import com.ghj.packageoftool.linkdb;/*运行本程序前需执行的脚本:delimiter $$//delimiter和$$之间要么没有空格要么只有一个空格,如果有多个空格,在执行创建存储过程语句时你会发现这样是不能创建成功的create procedure noparam()beginselect avg(price) as priceavg from fruit;end$$delimiter ;*//** * 没有任何输入和输出参数的存储过程 * * @author gaohuanjie */public class noparam { public static void main(string args[]) throws sqlexception { connection connection = linkdb.getmysqlconnection(); string prostr = {call noparam}; callablestatement callablestatement = connection.preparecall(prostr); callablestatement.execute(); resultset resultset = callablestatement.getresultset(); while (resultset.next()) { system.out.println(产品的平均价格是: + resultset.getdouble(priceavg) + 元); } linkdb.close(connection, callablestatement, resultset); }}
2、只有两个输入参数的存储过程
package com.ghj.packageoftest;import java.sql.callablestatement;import java.sql.connection;import java.sql.resultset;import java.sql.sqlexception;import com.ghj.packageoftool.linkdb;/*运行本程序前需执行的脚本:delimiter $$create procedure intwoparam(in fruitname varchar(12),in fruitprice decimal(9,2))//说明:fruitprice参数的数据类型与price列的数据类型不一致(price的类型为(8,2)),对这一现象应该有所感悟。beginselect * from fruit where name like concat('%',fruitname,'%') and price < fruitprice;//注意:concat('%',fruitname,'%')不能为'%'+fruitname+'%'end$$delimiter ;*//** * 只有两个输入参数的存储过程 * * @author gaohuanjie */public class intwoparam { public static void main(string args[]) throws sqlexception { connection connection = linkdb.getmysqlconnection(); string procstr = {call intwoparam(?,?)}; callablestatement callablestatement = connection.preparecall(procstr); callablestatement.setstring(1, 莲); callablestatement.setdouble(2, 88.88);//对decimal类型的属性设值要使用setdouble方法。 callablestatement.execute(); resultset resultset = callablestatement.getresultset(); system.out.println(名称包含‘莲’字且价格小于88.88元的水果有:); while (resultset.next()) { system.err.println(名称: + resultset.getstring(name) +、价格: + resultset.getdouble(price) + 元+、产地: + resultset.getstring(address)); } linkdb.close(connection, callablestatement, resultset); }}
3、只有两个输出参数的存储过程
package com.ghj.packageoftest;import java.sql.callablestatement;import java.sql.connection;import java.sql.sqlexception;import java.sql.types;import com.ghj.packageoftool.linkdb;/*运行本程序前需执行的脚本:delimiter $$create procedure outtwoparam(out fruitname varchar(12),out fruitprice decimal(5,3) )beginselect name into fruitname from fruit where name='莲雾';select price into fruitprice from fruit where name='莲雾';end $$delimiter ;注意:上面两条查询语句不能合成一个sql语句——select name into fruitname, price into fruitprice from fruit where name='莲雾';*//** * 只有两个输出参数的存储过程 * * @author gaohuanjie */public class outtwoparam { public static void main(string args[]) throws sqlexception { connection connection = linkdb.getmysqlconnection(); string prostr = {call outtwoparam(?,?)}; callablestatement callablestatement = connection.preparecall(prostr); callablestatement.registeroutparameter(1, types.varchar); callablestatement.registeroutparameter(2, types.decimal); callablestatement.execute(); string fruitname = callablestatement.getstring(1); double fruitprice = callablestatement.getdouble(2);// 获取decimal类型的属性要使用getdouble方法。 system.out.println(水果名称: + fruitname +、水果价格: + fruitprice + 元); linkdb.close(connection, callablestatement, null); }}
4、含有一个输入参数和一个输出参数的存储过程
package com.ghj.packageoftest;import java.sql.callablestatement;import java.sql.connection;import java.sql.sqlexception;import java.sql.types;import com.ghj.packageoftool.linkdb;/*运行本程序前需执行的脚本:delimiter $$create procedure inoneparamandoutoneparam(in fruitname varchar(12),out fruitprice decimal(7,3))beginselect price from fruit where name=fruitname into fruitprice;end $$delimiter ;*/ /** * 含有一个输入参数和一个输出参数的存储过程 * * @author gaohuanjie */public class inoneparamandoutoneparam { public static void main(string args[]) throws sqlexception { connection connection=linkdb.getmysqlconnection(); callablestatement callablestatement=null; string procstr={call inoneparamandoutoneparam(?,?)}; callablestatement=connection.preparecall(procstr); string fruitname = 莲雾; callablestatement.setstring(1, fruitname); callablestatement.registeroutparameter(2, types.decimal); callablestatement.execute(); double fruitprice=callablestatement.getdouble(2);//获取decimal类型的属性要使用getdouble方法。 system.out.println(fruitname+的价格为:+fruitprice+元); linkdb.close(connection, callablestatement, null); }}
5、输入参数即输出参数的存储过程
package com.ghj.packageoftest;import java.sql.*;import com.ghj.packageoftool.linkdb;/* 运行本程序前需执行的脚本:delimiter $$create procedure inoneparamisoutoneparam(inout fruitname varchar(12))beginselect name into fruitname from fruit where name like concat('%', fruitname, '%') limit 0,1;end $$delimiter ;或delimiter $$create procedure inoneparamisoutoneparam(inout fruitname varchar(12))beginselect name from fruit where name like concat('%', fruitname, '%') limit 0,1 into fruitname;end $$delimiter ;注意上面查询语句不能这样写:select name from fruit where name like concat('%', fruitname, '%') into fruitname limit 0,1;注意:对比3、4和5java文件内创建存储过程脚本中“into”关键字的位置你一定深有收获,呵呵呵,偷点懒,在此就不总结了。*//** * 输入参数即输出参数的存储过程 * * @author gaohuanjie */public class inoneparamisoutoneparam { public static void main(string args[]) throws sqlexception { connection con = linkdb.getmysqlconnection(); callablestatement callablestatement = null; string procstr = {call inoneparamisoutoneparam(?)}; callablestatement = con.preparecall(procstr); callablestatement.setstring(1, 莲); callablestatement.registeroutparameter(1, types.varchar); callablestatement.execute(); string fruitname = callablestatement.getstring(1); system.out.println(表中水果名称含有‘莲’字的一中水果的名称是: + fruitname); linkdb.close(con, callablestatement, null); }}
说明:
1、如果把上面代码拷贝下来你会发现缺少linkdb类,现贴出该类:
package com.ghj.packageoftool;import java.sql.connection;import java.sql.drivermanager;import java.sql.preparedstatement;import java.sql.resultset;import java.sql.sqlexception;/** * 连接数据库 * * @author gaohuanjie */public class linkdb { /** * 功能:获取与mysql的连接 * * @author gaohuanjie */ public static connection getmysqlconnection() { connection connection = null; string url = jdbc:mysql://localhost:3306/test; string user = root; string pwd = ; string drivername = com.mysql.jdbc.driver; try { class.forname(drivername); connection = drivermanager.getconnection(url, user, pwd); } catch (classnotfoundexception e) { e.printstacktrace(); } catch (sqlexception e) { e.printstacktrace(); } return connection; } /** * 关闭释放所有的资源 * * @author gaohuanjie */ public static void close(connection con, preparedstatement ps, resultset rs) { if (rs != null){ try { rs.close(); } catch (sqlexception e) { e.printstacktrace(); } } if (ps != null){ try { ps.close(); } catch (sqlexception e) { e.printstacktrace(); } } if (con != null){ try { con.close(); } catch (sqlexception e) { e.printstacktrace(); } } }}
2、如果执行创建存储过程的sql脚本,你会发现缺少名为fruit类,现贴出创建该表的sql语句:
create database `test`;use `test`;create table `fruit` ( `id` char(36) not null comment '标识', `name` varchar(12) not null comment '名称', `price` decimal(8,2) not null comment '单价', `address` varchar(300) default null comment '产地', primary key (`id`)) engine=innodb default charset=utf8 comment='水果表';insert into `fruit`(`id`,`name`,`price`,`address`) values ('27640c30-8df5-4cf2-916e-c28e0b2b1b52','山竹','24.45','马来西亚'),('46ac8392-9922-4593-89a3-517a9e516733','菠萝','19.41','巴西'),('63061a9f-3a0e-4140-98e0-8b1e13e4eab3','哈密瓜','17.77','中国'),('7ef0c286-b8b1-4e1e-9a8a-36bce703cf18','鳄梨','30.80','墨西哥'),('a1cf5251-9311-4c7f-be10-3532d8c16291','树莓','117.50','瑞士'),('c397aed0-a39a-49c5-91ee-7fc0579ddb20','莲雾','77.33','印度尼西亚'),('e8068fa1-a8e7-4025-89e2-36c1d5d23c74','榴莲','16.50','泰国');
【0分下载演示资源】