什么是存储过程
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。
存储过程有什么用?
优点
.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
2.当对数据库进行复杂操作时(如对多个表进行Update,Insert,Query,Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。
3.存储过程可以重复使用,可减少数据库开发人员的工作量
4.安全性高,可设定只有某些用户才具有对指定存储过程的使用权
有一点需要注意的是,一些网上盛传的所谓的存储过程要比sql语句执行更快的说法,实际上是个误解,并没有根据,包括微软内部的人也不认可这一点,所以不能作为正式的优点,希望大家能够认识到这一点。
缺点
1:调试麻烦,但是用 PL/SQL Developer 调试很方便!弥补这个缺点。
2:移植问题,数据库端代码当然是与数据库相关的。但是如果是做工程型项目,基本不存在移植问题。
3:重新编译问题,因为后端代码是运行前编译的,如果带有引用关系的对象发生改变时,受影响的存储过程、包将需要重新编译(不过也可以设置成运行时刻自动编译)。
4: 如果在一个程序系统中大量的使用存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,最后如果用户想维护该系统可以说是很难很难、而且代价是空前的,维护起来更麻烦。
存储过程与触发器
触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。所以运行触发器就叫触发或点火(firing)。ORACLE事件指的是对数据库的表进行的INSERT、UPDATE及DELETE操作或对视图进行类似的操作。可以将触发器看作一个特殊的存储过程,不通过名字调用,通过事件直接触发。
存储过程的写法
sql server:
sqlserver
生成存储
CREATE PROCEDURE myTest
@userId int
AS
BEGIN
SELECT * from AccountsInfo where UserID=@userId
END
GO
执行存储
EXEC [dbo].[myTest]
@UserID = 9849577
GO
以上是简单的调用:
带参无返回:
带参有返回:
带参多值
多个存储相互调用
JAVA项目中如何调用存储过程
mybaits:
/**
* 重置用户保护密码
*
* @param map userId:用户id
* pwd:用户密码
* ip:用户ip
* ret:返回值
* -1:失败
* >0: 成功
*/
@Select({"{ call Game_WEB_Protect_ResetPassWord(#{userId},#{pwd},#{ip},#{ret,mode=OUT,jdbcType=INTEGER}) }"})
@Options(statementType = StatementType.CALLABLE)
void resetPassWord(Map<String, Object> map);
存储过程返回多结果集
使用mapper.xml中定义resultmap
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.fuyun.front.pay.payapi.mapper.monthcard.MonthCardMapper">
<resultMap id="MonthCardInfo" type="com.fuyun.front.pay.payapi.dos.monthcard.MonthCardInfoDo">
<result property="rid" column="rid"/>
<result property="name" column="name"/>
<result property="days" column="days"/>
<result property="price" column="price"/>
<result property="isdiscount" column="isdiscount"/>
<result property="discount" column="discount"/>
<result property="state" column="state"/>
<result property="addtime" column="addtime"/>
<result property="reserved" column="reserved"/>
</resultMap>
<resultMap id="MonthCardTypeInfo" type="com.fuyun.front.pay.payapi.dos.monthcard.MonthCardTypeInfoDo">
<result property="rid" column="rid"/>
<result property="mcTypeName" column="mcTypeName"/>
<result property="mcTypeNum" column="mcTypeNum"/>
<result property="mcTypeId" column="mcTypeId"/>
</resultMap>
</mapper>
在 mapper中定义结果为resultmap
/**
* 获取月卡充值列表信息
* return
*/
@ResultMap({"MonthCardInfo","MonthCardTypeInfo"})
@Select("{ call Game_Web_Match_GetMonthCardList() }")
@Options(statementType = StatementType.CALLABLE)
List<List<?>> getMonthCardList();
Test
@Test
public void monthCardMapper(){
List<List<?>> object = monthCardMapper.getMonthCardList();
List<MonthCardInfoDo> monthCardInfoList = (List<MonthCardInfoDo>) object.get(0);
List<MonthCardTypeInfoDo> monthCardTypeInfoList = (List<MonthCardTypeInfoDo>) object.get(1);
System.out.println( monthCardInfoList.toString());
System.out.println( monthCardTypeInfoList.toString());
}