存储过程+游标+事务
2016-06-22 13:41
260 查看
一丶 存储过程
什么是存储过程:存储过程可以说是一个记录集吧,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了
存储过程的好处:
1.由于数据库执行动作时,是先编译后执行的。然而存储过程是一个编译过的代码块,所以执行效率要比T-SQL语句高。
2.一个存储过程在程序在网络中交互时可以替代大堆的T-SQL语句,所以也能降低网络的通信量,提高通信速率。
3.通过存储过程能够使没有权限的用户在控制之下间接地存取数据库,从而确保数据的安全。
存储过程的一些基本语法:
1. 只返回单一记录集的存储过程
-------------创建名为GetUserAccount的存储过程----------------
create Procedure GetUserAccount
as
select * from UserAccount
go
-------------执行上面的存储过程----------------
exec GetUserAccount
2.没有输入输出的存储过程
-------------创建名为GetUserAccount的存储过程----------------
create Procedure inUserAccount
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(9,9,'2013-01-02',9)
go
-------------执行上面的存储过程----------------
exec inUserAccount
3.有返回值的存储过程
-------------创建名为GetUserAccount的存储过程----------------
create Procedure inUserAccountRe
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(10,10,'2013-01-02',10)
return @@rowcount
go
-------------执行上面的存储过程----------------
exec inUserAccountRe
4.有输入参数和输出参数的存储过程
5.
同时具有返回值、输入参数、输出参数的存储过程
6.同时返回参数和记录集的存储过程
7.返回多个记录集的存储过程
二丶 游标
在关系数据库中,我们对于查询的思考是面向集合的。
而游标则是面向行的。
游标的写法:
打开游标:
循环读取游标:
next:declare test_course cursor for select *from [dbo].[Info_User]
open test_course fetch next from test_course
while @@fetch_status=0
begin
fetch next from test_course
end
(FIRST),最后一行(LAST),下一行(NEXT),上一行(PRIOR),直接跳到某行(ABSOLUTE(n)),相对于目前跳几行(RELATIVE(n)):
对于使用这些参数来读取数据必须指定scroll选项:
三丶 事务
事务:保持逻辑数据一致性与可恢复性,必不可少的利器。
书面解释:事务具有原子性,一致性,隔离性,持久性。
原子性:事务必须是一个自动工作的单元,要么全部执行,要么全部不执行。
一致性:事务结束的时候,所有的内部数据都是正确的。
隔离性:并发多个事务时,各个事务不干涉内部数据,处理的都是另外一个事务处理之前或之后的数据。
持久性:事务提交之后,数据是永久性的,不可再回滚
存储过程+游标+事务
ALTER procedure [dbo].[ExpertOrderBack]
AS
--声明几个变量
declare @UserID int-- 提问的用户ID
declare @ExpertUserID int --回答问题的专家ID
declare @ExpertID int
declare @Baodan decimal --报单账户
declare @Price decimal --咨询一次的价格
declare @errors int
declare @ID int
declare mycursor cursor for select ID,ExpertID,UserID from ExpertOrder where OrderState=0 and OdertTime<dateadd(day,-7,getdate())
--打开游标
open mycursor
--从游标里取出数据赋值到我们刚才声明的3个变量中
fetch next from mycursor into @ID,@ExpertID,@UserID
--判断游标的状态
-- 0 fetch语句成功
---1 fetch语句失败或此行不在结果集中
---2 被提取的行不存在
while (@@fetch_status=0)
begin
--通过ExpertID 获取专家对应的用户ID
Select @ExpertUserID=(select UserId from Expert where ID=@ExpertID)
Select @Price=(select Price from Expert where ID=@ExpertID)
Select @Baodan=(select BaodanGold from Info_User where UserID=@ExpertUserID)
begin tran --开始执行事务
--判断用户的金额是否足够
if @Baodan<@Price
begin
set @errors=@@ERROR+1
end
--开始进行业务上变动
update ExpertOrder set OrderState=3,IsSatisfaction=1,IsAudit=1 where ID=@ID
insert Info_Transaction(UserID,TranUserAccountType,TranType,BeforeTranMoney,TranMeney,EndTranMoney,Notes,IsCancel,TranCurrency,AddTime,IsDelete) values(@ExpertUserID,0,9,@Baodan,@Price,@Baodan+@Price,'会员未确认,系统自动扣款',0,'人民币',GETDATE(),0)
update Info_User set BaodanGold=@Baodan+@Price where UserID=@ExpertUserID
if @errors<>0 --判断 如果两条语句有任何一条出现错误。(如果前面的SQL 语句执行没有错误,则返回0)
begin
print '出现错误'
rollback tran --开始执行事务的回滚,恢复转账开始之前的状态
return 0
end
else --如果两个语句都执行成功
begin
commit tran --执行这个事务的操作
end
print '游标成功取出一条数据'
print @ExpertID
print @UserID
print @ID
fetch next from mycursor into @ID,@ExpertID,@UserID
end
--关闭游标
close mycursor
--撤销游标
DEALLOCATE mycursor
什么是存储过程:存储过程可以说是一个记录集吧,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了
存储过程的好处:
1.由于数据库执行动作时,是先编译后执行的。然而存储过程是一个编译过的代码块,所以执行效率要比T-SQL语句高。
2.一个存储过程在程序在网络中交互时可以替代大堆的T-SQL语句,所以也能降低网络的通信量,提高通信速率。
3.通过存储过程能够使没有权限的用户在控制之下间接地存取数据库,从而确保数据的安全。
存储过程的一些基本语法:
1. 只返回单一记录集的存储过程
-------------创建名为GetUserAccount的存储过程----------------
create Procedure GetUserAccount
as
select * from UserAccount
go
-------------执行上面的存储过程----------------
exec GetUserAccount
2.没有输入输出的存储过程
-------------创建名为GetUserAccount的存储过程----------------
create Procedure inUserAccount
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(9,9,'2013-01-02',9)
go
-------------执行上面的存储过程----------------
exec inUserAccount
3.有返回值的存储过程
-------------创建名为GetUserAccount的存储过程----------------
create Procedure inUserAccountRe
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(10,10,'2013-01-02',10)
return @@rowcount
go
-------------执行上面的存储过程----------------
exec inUserAccountRe
4.有输入参数和输出参数的存储过程
-------------创建名为GetUserAccount的存储过程---------------- create Procedure GetUserAccountRe @UserName nchar(20), @UserID int output as if(@UserName>5) select @UserID=COUNT(*) from UserAccount where UserID>25 else set @UserID=1000 go -------------执行上面的存储过程---------------- exec GetUserAccountRe '7',null
5.
同时具有返回值、输入参数、输出参数的存储过程
-------------创建名为GetUserAccount的存储过程---------------- create Procedure GetUserAccountRe1 @UserName nchar(20), @UserID int output as if(@UserName>5) select @UserID=COUNT(*) from UserAccount where UserID>25 else set @UserID=1000 return @@rowcount go -------------执行上面的存储过程---------------- exec GetUserAccountRe1 '7',null
6.同时返回参数和记录集的存储过程
-------------创建名为GetUserAccount的存储过程---------------- create Procedure GetUserAccountRe2 @UserName nchar(20), @UserID int output as if(@UserName>5) select @UserID=COUNT(*) from UserAccount where UserID>25 else set @UserID=1000 select * from UserAccount return @@rowcount go -------------执行上面的存储过程---------------- exec GetUserAccountRe2 '7',null
7.返回多个记录集的存储过程
-------------创建名为GetUserAccount的存储过程---------------- create Procedure GetUserAccountRe3 as select * from UserAccount select * from UserAccount where UserID>5 go -------------执行上面的存储过程---------------- exec GetUserAccountRe3
二丶 游标
在关系数据库中,我们对于查询的思考是面向集合的。
而游标则是面向行的。
游标的写法:
declare test_course(定义的变量名) cursor for select *from 表名
打开游标:
open test_course
循环读取游标:
next:declare test_course cursor for select *from [dbo].[Info_User]
open test_course fetch next from test_course
while @@fetch_status=0
begin
fetch next from test_course
end
(FIRST),最后一行(LAST),下一行(NEXT),上一行(PRIOR),直接跳到某行(ABSOLUTE(n)),相对于目前跳几行(RELATIVE(n)):
对于使用这些参数来读取数据必须指定scroll选项:
declare test_two cursor scroll for select *from [dbo].[Info_User] open test_two fetch LAST from test_two
使用 FETCH 将值存入变量
fetch next from mycursor into @ID,@ExpertID,@UserID
三丶 事务
事务:保持逻辑数据一致性与可恢复性,必不可少的利器。
书面解释:事务具有原子性,一致性,隔离性,持久性。
原子性:事务必须是一个自动工作的单元,要么全部执行,要么全部不执行。
一致性:事务结束的时候,所有的内部数据都是正确的。
隔离性:并发多个事务时,各个事务不干涉内部数据,处理的都是另外一个事务处理之前或之后的数据。
持久性:事务提交之后,数据是永久性的,不可再回滚
create procedure mon --创建存储过程,定义几个变量 @toID int, --接收转账的账户 @fromID int , --转出自己的账户 @momeys money --转账的金额 as begin tran --开始执行事务 update bb set moneys=moneys-@momeys where ID=@fromID -执行的第一个操作,转账出钱,减去转出的金额 update bb set moneys=moneys+@momeys where ID=@toID --执行第二个操作,接受转账的金额,增加 if @@error<>0 --判断如果两条语句有任何一条出现错误 begin rollback tran –开始执行事务的回滚,恢复的转账开始之前状态 return 0 end go else --如何两条都执行成功 begin commit tran 执行这个事务的操作 return 1 end go
存储过程+游标+事务
ALTER procedure [dbo].[ExpertOrderBack]
AS
--声明几个变量
declare @UserID int-- 提问的用户ID
declare @ExpertUserID int --回答问题的专家ID
declare @ExpertID int
declare @Baodan decimal --报单账户
declare @Price decimal --咨询一次的价格
declare @errors int
declare @ID int
declare mycursor cursor for select ID,ExpertID,UserID from ExpertOrder where OrderState=0 and OdertTime<dateadd(day,-7,getdate())
--打开游标
open mycursor
--从游标里取出数据赋值到我们刚才声明的3个变量中
fetch next from mycursor into @ID,@ExpertID,@UserID
--判断游标的状态
-- 0 fetch语句成功
---1 fetch语句失败或此行不在结果集中
---2 被提取的行不存在
while (@@fetch_status=0)
begin
--通过ExpertID 获取专家对应的用户ID
Select @ExpertUserID=(select UserId from Expert where ID=@ExpertID)
Select @Price=(select Price from Expert where ID=@ExpertID)
Select @Baodan=(select BaodanGold from Info_User where UserID=@ExpertUserID)
begin tran --开始执行事务
--判断用户的金额是否足够
if @Baodan<@Price
begin
set @errors=@@ERROR+1
end
--开始进行业务上变动
update ExpertOrder set OrderState=3,IsSatisfaction=1,IsAudit=1 where ID=@ID
insert Info_Transaction(UserID,TranUserAccountType,TranType,BeforeTranMoney,TranMeney,EndTranMoney,Notes,IsCancel,TranCurrency,AddTime,IsDelete) values(@ExpertUserID,0,9,@Baodan,@Price,@Baodan+@Price,'会员未确认,系统自动扣款',0,'人民币',GETDATE(),0)
update Info_User set BaodanGold=@Baodan+@Price where UserID=@ExpertUserID
if @errors<>0 --判断 如果两条语句有任何一条出现错误。(如果前面的SQL 语句执行没有错误,则返回0)
begin
print '出现错误'
rollback tran --开始执行事务的回滚,恢复转账开始之前的状态
return 0
end
else --如果两个语句都执行成功
begin
commit tran --执行这个事务的操作
end
print '游标成功取出一条数据'
print @ExpertID
print @UserID
print @ID
fetch next from mycursor into @ID,@ExpertID,@UserID
end
--关闭游标
close mycursor
--撤销游标
DEALLOCATE mycursor
相关文章推荐
- 将MathType公式粘贴到文档中的方法
- tcp-backlog配置
- ThinkPHP中M方法与D方法有什么区别
- Linux中无法连接127.0.0.1
- java生成.h文件命令javah使用方式
- PhotoView 源码解析
- 为什么发了个博客分分钟被各种网站花式转载=。=而不通知我
- mysqldump & binlog做完全备份
- android 仿小米日历 周视图 月视图切换
- MongoDB之十大应用设计技巧
- lokijs
- eclipse中快速定位当前文件所在的位置
- 安装CocoaPods
- Sqlserver根据表名生成insert 插入语句的sql
- Linux下字符串的截取
- cmd命令提示符中,如何清屏
- cmd命令提示符中,如何清屏
- cmd命令提示符中,如何清屏
- cmd命令提示符中,如何清屏
- cmd命令提示符中,如何清屏