SQL - Server存储过程学习总结讲解
更新时间:2024-03-28 13:20:01 阅读量: 综合文库 文档下载
- sql server推荐度:
- 相关推荐
SQL Server数据库:存储过程学习总结
一、SQL Server生成唯一值的方法
NEWID() -- SQL Server中生成唯一序列值的函数。 SYS_GUID() --Oracle中生成唯一序列值的函数。
二、事务的应用Transaction
SQL Server中的Transaction,需显示开启,提交/回滚,且一个Transaction必须要有Commit Transaction/Rollback Transaction。且Commit/Rollback一定要在return之前。
在存储过程中试用Transaction的示例: IF EXISTS (SELECT * FROM SYSOBJECTS WHERE name='my_sp_test' AND TYPE='P') BEGIN DROP PROCEDURE my_sp_test; END; GO create procedure my_sp_test @i int, @outstr varchar(100) out as begin try begin transaction -- 事务开启 declare @j int; if @i<10 begin set @outstr = '直接Return,并未Commit或Rollback Transaction.'; return; end else begin set @outstr = '抛出自定义异常,并在异常捕获处Rollback Transaction.'; RAISERROR (66666, -- Message id. 16, -- Severity, 1 -- State, ) ; end; commit transaction; -- 提交事务 end try begin catch if @@ERROR=66666 begin -- 判断是否存在开启的事务,避免如果事务在这之前已提交或者已回滚,再次回滚会抛异常 if(@@TRANCOUNT <> 0) begin rollback transaction; -- 事务回滚 end; end; return; end catch; go 测试存储过程,如下代码: /* 第一个入参= 12,不会产生异常 */ DECLARE @OUTSTR_test VARCHAR(100); exec dbo.my_sp_test 12,@OUTSTR_test out print @OUTSTR_test ; -- @OUTSTR_test = '抛出自定义异常,并在异常捕获处Rollback Transaction.' /* 第一个入参= 8,执行后则会出现异常,异常信息如下行 * 'EXECUTE 后的事务计数指示BEGIN 和COMMIT 语句的数目不匹配。上一计数= 0,当前计数= 1。' */ DECLARE @OUTSTR_test_1 VARCHAR(100); exec dbo.my_sp_test 8,@OUTSTR_test_1 out print @OUTSTR_test_1 ; -- @OUTSTR_test_1 = '直接Return,并未Commit或Rollback Transaction.' /* 入参为8的测试语句执行后,之所以会出现异常,是因为Begin Transaction后,在之后 * 的代码中未对这个Transaction进行Commit或者Rollback的操作。 */ 三、游标的应用Cursor
SQL Server中的游标声名后,一定要显示的释放。若未释放,再次执行时,则会出现“游标XX已经存在”的异常。Open游标后,一定要显示的Close。
在存储过程中试用Cursor的示例: IF EXISTS (SELECT * FROM SYSOBJECTS WHERE name='my_sp_test' AND TYPE='P') BEGIN DROP PROCEDURE my_sp_test; END; GO create procedure my_sp_test @i int, @outstr varchar(100) out as declare @loginName varchar(100); declare cur_user cursor for select ESUS_LOGIN_NAME from ES_USER where ESUS_ESCO_ID='100004'; begin try open cur_user; -- 开启游标 fetch next from cur_user into @loginName; while @@FETCH_STATUS = 0 begin if(@i >=10) begin set @outstr = 'login name: '+@loginName; RAISERROR (66666, -- Message id. 16, -- Severity, 1 -- State, ) ; end else if (@i<10) begin set @outstr = 'login name: '+@loginName; end; fetch next from cur_user into @loginName; end; close cur_user; -- 关闭游标 return; end try begin catch if @@ERROR = 66666 begin close cur_user; -- 关闭游标 deallocate cur_user;-- 释放游标 end; return; end catch; go 测试存储过程,如下代码: /* 第一个入参= 12,不会产生异常 */ DECLARE @OUTSTR_test VARCHAR(100); exec dbo.my_sp_test 12,@OUTSTR_test out print @OUTSTR_test ; -- @OUTSTR_test = 'login name: ryan' /* 第一个入参= 8,执行第二次后则会出现下行的异常 * '名为'cur_user' 的游标已存在。' */ DECLARE @OUTSTR_test_1 VARCHAR(100); exec dbo.my_sp_test 8,@OUTSTR_test_1 out print @OUTSTR_test_1 ; -- @OUTSTR_test_1 = 'login name: vicky' /* 入参为8的测试语句执行第二次,之所以会出现异常,是因为没有将游标释放就return了。所以有使用游标的存储过程,在return之前一定要显示的释放游标。 */
四、自定义异常的试用RaisError 在使用SQL Server存储过程或者触发器时,通常会使用自定义异常来处理一些特殊逻辑。例如游标的销毁,事务的回滚。接下来将会详细的介绍SQL Server自定义异常的使用。 使用“raiserror”来抛出自定义异常。如下代码:在存储过程中,抛出自定义异常,然后在catch块中捕获自定义异常。 IF EXISTS (SELECT * FROM SYSOBJECTS WHERE name='my_sp_test' AND TYPE='P') BEGIN DROP PROCEDURE my_sp_test; END; GO create procedure my_sp_test @i int, @outstr varchar(100) out as begin try declare @j int; if @i<10 begin set @outstr = 'system exception.'; set @j = 10/0; end else begin set @j = @i; set @outstr = 'customer exception 11111111111111111'; RAISERROR (66666, -- Message id. 16, -- Severity, 1 -- State, ) ; end; end try begin catch if @@ERROR=66666 begin set @outstr = @outstr + '---------------- customer exception'; end; return; end catch; go 如上代码,raiserror参数说明: (1). Message id:异常的唯一标识,且这个值会被赋值给SQLServer的系统变量@@Error。自定义异常的Message Id建议使用50000以后的,因为50000以内的会被系统异常占用。 (2). Severity:异常的级别。 可输入1—19的数值。1—10之间不会被catch捕获。19以后是非常严重的级别。 (3). State : 如果输入负值或大于255 的值会生成错误,产生错误则会中断数据库的连接。执行该存储过程,看看自定义异常是否成功捕获: DECLARE @OUTSTR11 VARCHAR(100); exec dbo.my_sp_test 12,@OUTSTR11 out print @OUTSTR11; 五、Java调用SQL Server存储过程 1、JDBC方式调用
Java代码: public class invokeSP { public static void main(String[] args) { String driverClassName=\; String url=\; String username=\; String password=\; Connection cn = null; try { Class.forName(driverClassName); cn = DriverManager.getConnection(url,username,password); // 返回單個結果的存儲過程 outputProcedure(cn); // // 返回结果集的存储过程 resultProcedure(cn); } catch (Exception e) { e.printStackTrace(); }finally{ try { cn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 调用返回单个结果集的存储过程 */ public static void resultProcedure(Connection conn){ String sql = \; CallableStatement cstmt = null; ResultSet rs = null; try { cstmt = conn.prepareCall(sql); cstmt.setInt(1, 12); cstmt.setString(2, \); cstmt.setString(3, \); cstmt.registerOutParameter(\, java.sql.Types.VARCHAR); cstmt.registerOutParameter(\, java.sql.Types.VARCHAR); rs = cstmt.executeQuery(); while(rs.next()){ System.out.println(\+rs.getString(\)); } System.out.println(\+cstmt.getString(\)); System.out.println(\+cstmt.getString(\)); } catch (SQLException e) { e.printStackTrace(); }finally{ try { rs.close(); cstmt.close();
} } catch (SQLException e) { e.printStackTrace(); } } } /** * 调用只返回单个字段的存储过程 */ public static void outputProcedure(Connection conn){ String sql = \; CallableStatement cstmt = null; try { cstmt = conn.prepareCall(sql); cstmt.setInt(1, 12); cstmt.setString(2, \); cstmt.setString(3, \); cstmt.registerOutParameter(\, java.sql.Types.VARCHAR); cstmt.registerOutParameter(3, java.sql.Types.VARCHAR); cstmt.execute(); System.out.println(\ + cstmt.getString(2)); System.out.println(\ + cstmt.getString(3)); } catch (SQLException e) { e.printStackTrace(); }finally{ try { cstmt.close(); } catch (SQLException e) { e.printStackTrace(); } } } SQL存储过程代码: IF EXISTS (SELECT * FROM SYSOBJECTS WHERE name='my_sp_test' AND TYPE='P') BEGIN DROP PROCEDURE my_sp_test; END; GO create procedure my_sp_test @i int, @outstr varchar(100) out,@returnCode varchar(100) out as begin try begin tran declare @j int; set @returnCode = @returnCode +';OUT PUT 参数测试'; if @i<10 begin set @outstr = 'system exception.'; set @j = 10/0; --rollback tran; --return; end else begin begin try if @i>=20 begin set @outstr = 'customer exception 2222222222222222'; set @j = 10/0; end else begin set @j = @i; set @outstr = 'customer exception 11111111111111111'; select * from CD_BILL_NO_RULE where CREATOR = '150' AND REC_VER =0; --select * from ES_USER where ESUS_ESCO_ID = 100; RAISERROR (66666, -- Message id. 16, -- Severity, 1 -- State, ) ; end; end try begin catch raiserror(66666,16,1); set @outstr = 'customer exception 333333333333333333'; end catch; end; commit tran; end try begin catch if @@ERROR=66666 begin set @outstr = @outstr + '---------------- customer exception'; end; rollback tran; return; end catch; go 2、Spring方式调用
使用Spring调用SQLServer存储过程与Oracle存储过程的差别: 1、调用一个返回结果集的存储过程 SQL Server:
super.declareParameter(new SqlReturnResultSet(name,
ParameterizedBeanPropertyRowMapper.newInstance(entityTypeClass)));
Oracle:
super.declareParameter(new SqlOutParameter(name,OracleTypes.CURSOR,
ParameterizedBeanPropertyRowMapper.newInstance(entityTypeClass));
注:(1). SQL Server定义返回结果集的存储过程,只需在存储过程中执行一个查询语句即可。但是这个查询语句必 须在transaction中。
(2). SQL Server存储过程返回的结果集因为没有定义具体的变量名,所以我们在获取结果集的时候,直接写 “default”即可。
sp.addResultSetParameter(\, CdBillNoRuleModel.class); Map
List
result.get(\); (3). 如果存储过程中有返回多个结果集,则不能直接用“default”来获取结果集,而是用“result-set-*”。
sp.addResultSetParameter(\, CdBillNoRuleModel.class); sp.addResultSetParameter(\, EsUserModel.class); Map
List
result.get(\);
List
result.get(\); Java代码 —— 测试类代码:
public class SpringInvokeSP { public static void main(String[] args) { String driverClassName=\; String url=\; String username=\; String password=\; // 创建datasource DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName(driverClassName); ds.setUrl(url); ds.setUsername(username); ds.setPassword(password); resultSP(ds); } /** * 返回多个结果集的存储过程 * @param ds */ public static void resultSP(DriverManagerDataSource ds){ SQLStoredProcedure sp = new SQLStoredProcedure(ds,\); sp.addParameter(\, 11); sp.addOutStringParameter(\); sp.addInOutParameter(\, \); sp.addOutDateParameter(\); sp.addOutDateParameter(\); sp.addResultSetParameter(\, CdBillNoRuleModel.class); sp.addResultSetParameter(\, EsUserModel.class); Map
} public void addOutDoubleParameter(String name) { super.declareParameter(new SqlOutParameter(name, Types.DOUBLE)); } public void addOutDateParameter(String name) { super.declareParameter(new SqlOutParameter(name, Types.TIMESTAMP)); } public void addResultSetParameter(String name,Class> entityTypeClass){ super.declareParameter(new SqlReturnResultSet(name, ParameterizedBeanPropertyRowMapper.newInstance(entityTypeClass))); } public Map
IF EXISTS (SELECT * FROM SYSOBJECTS WHERE name='my_sp_test' AND TYPE='P') BEGIN DROP PROCEDURE my_sp_test; END; GO create procedure my_sp_test @i int, @outstr varchar(100) out,@returnCode varchar(100) out as begin try begin tran declare @j int; set @returnCode = @returnCode +';OUT PUT 参数测试'; if @i<10 begin set @outstr = 'system exception.'; set @j = 10/0; end else begin begin try if @i>=20 begin set @outstr = 'customer exception 2222222222222222'; set @j = 10/0; end else begin set @j = @i; set @outstr = 'customer exception 11111111111111111'; select * from CD_BILL_NO_RULE where CREATOR = '150' AND REC_VER =0; select * from ES_USER where ESUS_ESCO_ID = 100; RAISERROR (66666, -- Message id. 16, -- Severity, 1 -- State, ) ; end; end try begin catch raiserror(66666,16,1); set @outstr = 'customer exception 333333333333333333'; end catch; end; commit tran; end try begin catch if @@ERROR=66666 begin set @outstr = @outstr + '---------------- customer exception'; end; rollback tran; return; end catch; go
正在阅读:
长春龙家堡机场飞行区场道工程施工组织设计 - 图文01-28
线性表的操作算法09-18
水厂之旅作文600字06-23
山西医学检验专升本的近年信息03-18
适合于本公司的财务管理制度05-26
家长会随想作文800字06-21
2018年初中毕业年级教学工作汇报材料03-08
江苏省房屋建筑和市政基础设施工程质量监督工作实施细则04-11
-物料编码与物料选型04-12
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 讲解
- 存储
- 过程
- 总结
- Server
- 学习
- SQL
- 机械制图模块五
- 2018年浙江省单独考试招生文化考试语文试题答案及评分参考
- 2008年中级会计职称《经济法》真题及答案解析
- 本科马克思课程考试基础考题!
- 《摆的秘密》教案设计
- 中国高校校徽 - 图文
- 901运输巷喷浆安全技术措施
- 收音机与车载电话 - 图文
- 沿线设施设计内容
- 2015数学之友高考模拟(1)
- 《工厂供电(第3版)》刘介才(课后习题详细答案)
- 节能电力变压器生产线建设项目可行性研究报告
- 利用51单片机实现多功能数字钟
- 低温型风力发电机组技术规范(备案稿)分解
- 《建设法规》题库 副本
- 《汽车电气设备构造与维修》课程标准
- 河北省保定市2018届高三第二次模拟考试文综地理试题Word版含答案
- 湖北省八校2017届高三第二次联考文综历史试题汇总
- 2015年国家公务员考试面试热点预测:立法禁止啃老
- 人教版八年级历史下册集体备课教案全册2012年 - 图文