使用navicat--查询创建第一个简单的存储过程,在user表中插入一条数据。
DELIMITER //
CREATE PROCEDURE myProceDure(in a CHAR)
COMMENT '插入一条记录'
BEGIN
DECLARE userId char;
SET userId = a;
INSERT INTO sys_user (user_id,user_name,user_password) VALUES
(userId,'procedureName','procedurePassword');
END//
DELIMITER ;
#写法1
CALL myProceDure('3');
#写法2
SET @a = '3';
#SELECT @a;可以查看a的值
CALL myProceDure2(@a);
DELIMITER // :声明分隔符为//,将分隔符内的代码作为整体,而不是根据默认的分号,不做声明会报错
myProceDure :自定义的存储过程名称
in/out/inout a CHAR:分别代表 输入参数/输出/既是输入也是输出 参数名称 参数类型
过程体的开始与结束使用BEGIN与END进行标识
通过CALL进行调用存储过程,传递声明的参数,可以看到插入成功。
#查看m001中所有的存储过程
SHOW PROCEDURE STATUS WHERE db='m001';
#删除存储过程
DROP PROCEDURE myProceDure;
其他例如:
DELIMITER//
#根据name获取到id
CREATE PROCEDURE getId(in a varchar(36),out userId varchar(36))
BEGIN
SELECT user_id into userId FROM sys_user WHERE user_name = a;
END//
#根据id获取单条数据
CREATE PROCEDURE getUser(in a varchar(36))
BEGIN
DECLARE userId VARCHAR(36);
SET userId = a;
SELECT * FROM sys_user WHERE user_id = userId;
END//
#还原分隔符
DELIMITER ;
call getId('admin',@userId);
#根据getId获得的id获取单条数据
call getUser(@userId);
@Override
public void addUser(User user){
Query query = getSession().createSQLQuery("CALL myProceDure('9')");
query.executeUpdate();
}
和执行原生sql一样,遵循存储过程语法执行即可。
运行速度:存储过程创建的时候,数据库已经对其进行了一次解析和优化。存储过程一旦执行,在内存中就会保留一份这个存储过程,这样下次再执行同样的存储过程时,可以从内存中直接调用
减少网络传输:存储过程直接就在数据库服务器上跑,所有的数据访问都在数据库服务器内部进行,不需要传输数据到其它服务器,所以会减少一定的网络传输
可维护性:存储过程有些时候比程序更容易维护,这是因为可以实时更新(不涉及服务器)DB端的存储过程。有些bug,直接改存储过程里的业务逻辑就搞定了
增强安全性:提高代码安全,防止 SQL注入。这一点sql语句也可以做到。
可扩展性:应用程序和数据库操作分开,独立进行,而不是相互在一起。方便以后的扩展和DBA维护优化
1. SQL本身是一种结构化查询语言,擅长的是数据查询而非业务逻辑的处理
2. 如果要对存储过程的参数或者其返回数据进行更改,则仍需要更新程序中的代码以添加参数、更新调用等等【淡化可维护性的优点】
3. 开发调试复杂,由于IDE的问题,存储过程的开发调试要比一般程序困难
4. 没办法应用缓存。虽然有全局临时表之类的方法可以做缓存,但同样加重了数据库的负担。如果缓存并发严重,经常要加锁,那效率实在堪忧
5. 不支持群集,数据库服务器无法水平扩展,或者数据库的切割(水平或垂直切割)。数据库切割之后,存储过程并不清楚数据存储在哪个数据库中