关系数据库SQL之可编程性事务

前言

前面关系数据库SQL之可编程性函数(用户自定义函数)一文提到关系型数据库提供了可编程性的函数、存储过程、事务、触发器及游标,前文已介绍了函数、存储过程,本文来介绍一下事务的使用。(还是以前面的银行系统为例)

图片来自网络

概述

是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)特性。

语法

开始事务:事务开始的位置,就是单个逻辑工作单元的开始。
回滚事务:就是将数据恢复至事务开始的状态,一般是不满足条件或者是发生错误的时候执行该操作。
提交事务:事务结束的位置,就是单个逻辑工作单元成功执行后,改变数据状态。

--开始事务
BEGIN TRAN[SACTION]
--回滚事务,TRAN[SACTION]可省略
ROLLBACK TRAN[SACTION]
--提交事务
COMMIT TRAN[SACTION]

--事务使用
BEGIN TRAN[SACTION]
--这里是SQL语句块

上面的SQL语句块,需要在适当的位置加上COMMIT TRAN[SACTION],如果需要回滚可以有ROLLBACK TRAN[SACTION]

事务可以与存储过程联合使用。

特性

  • 原子性(Atomic)(Atomicity)

事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。通常,与某个事务关联的操作具有共同的目标,并且是相互依赖的。如果系统只执行这些操作的一个子集,则可能会破坏事务的总体目标。原子性消除了系统处理操作子集的可能性。

  • 一致性(Consistent)(Consistency)

事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。某些维护一致性的责任由应用程序开发人员承担,他们必须确保应用程序已强制所有已知的完整性约束。例如,当开发用于转帐的应用程序时,应避免在转帐过程中任意移动小数点。

  • 隔离性(Insulation)(Isolation)

由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。这称为隔离性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。当事务可序列化时将获得最高的隔离级别。在此级别上,从一组可并行执行的事务获得的结果与通过连续运行每个事务所获得的结果相同。由于高度隔离会限制可并行执行的事务数,所以一些应用程序降低隔离级别以换取更大的吞吐量。

  • 持久性(Duration)(Durability)

事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。

示例

  1. 创建一个带事务的存储过程:孙悟空要取钱,交易信息表里面插入交易信息,同时要更改账户表里面的余额
begin transaction
    if exists(select * from sysobjects where name = 'proc_getMoney')
    drop procedure proc_getMoney
    go
    create proc proc_getMoney
        @cardId varchar(19),
        @tranMoney money
    as
    declare @balance money
    select @balance = LeftMoney from CardInfo where CardID = @cardId
    if(@tranMoney <= @balance)
    begin
        insert into TransInfo values(@cardId,'取款',@tranMoney,default)
        if(@@ERROR=0)
        begin
            update CardInfo set LeftMoney = LeftMoney - @tranMoney where CardID = @cardId
            if(@@ERROR=0)
            begin
                commit transaction
                print 'OK'  
            end 
        end
        else
        begin
            rollback
            print 'error'
        end
    end
    else
            print '余额不足'
go
exec proc_getMoney '1324 3626 7532 1935',520
go
exec proc_getMoney '1027 3526 1536 1135',520
go
  1. 在存储过程内创建事务,根据用户输入的个人信息,实现银行卡开户,输出参数作为用户的银行卡卡号以及银行卡余额(开户时不仅要在用户信息表和银行卡表添加一条数据,也要在交易信息表中插入一条存款的记录,因为开卡时需要指定开卡金额,银行卡卡号自动生成)
if exists(select * from sysobjects where name = 'proc_openAccount')
drop procedure proc_openAccount
go
create proc proc_openAccount
    @CustName varchar(20),      --定义变量开户人姓名
    @IDCard varchar(18),        --定义变量开户人身份证号
    @TelePhone varchar(13),     --定义变量开户人电话号码
    @Address varchar(50),       --定义变量开户人住址
    @openMoney money            --定义变量开户存入现金金额
as
begin
begin transaction
    declare @CustID int,@CardID varchar(19)  --定义变量开户人的账户编号,开户的卡号
    exec proc_getCardNo  @CardID output --执行自动生成卡号的存储过程,将输出值赋给变量@CardID
        --向账户表中插入数据
        insert into AccountInfo values
        (@CustName,@IDCard,@TelePhone,@Address)
    if(@@error != 0)--如果出错
        rollback--事务回滚
    else
        begin
            set @CustID = @@identity     --获取生成账户的编号CustID
            --向银行卡表中插入数据
            insert into CardInfo values
            (@CardID,default,@CustID,'活期',getdate(),@openMoney,@openMoney,'否')
                if(@@error != 0)
                    rollback
                else
                    begin
                    --向交易表中插入数据
                    insert into TransInfo values
                    (@CardID,'存款',@openMoney,default)
                    if(@@error != 0)
                        begin
                            rollback
                            print '开户失败,插入数据错误!'
                        end
                    else
                        begin
                            print '开户成功!'
                            print '卡号为:' + @CardID
                        end
                    end
        end
commit transaction
end
go
exec proc_openAccount '八戒','422322001550135015','027-8658888','高老庄',250
go

附:
实现生产银行卡的存储过程,该存储过程能随机的产生一个卡号输出

if exists(select * from sysobjects where name = 'proc_getCardNo')
    drop procedure proc_getCardNo
    go
    create proc proc_getCardNo
        @CardNo varchar(19) output  --定义输出参数的类型
    as
    begin
        declare @day varchar(2) --定义日期
        set @day = dateName(dd,getdate())
        if @day<10  --如果日期小于10,要对其加'0'
        set @day = '0'+@day
        set @CardNo = convert(varchar(9),(dateName(yyyy,getdate())+' '
+ dateName(mm,getdate())))+@day+' '+ convert(varchar(10),(dateName(hh,getdate())
+dateName(mi,getdate())+' '+ subString(convert(varchar(6),rand(datepart(ms,getdate()))*1000000),1,5)))  
    end
go
declare @card varchar(19)
exec proc_getCardNo  @card output
print '卡号为:' + @card
go

本文就介绍到这里。
如有疑问请联系我。

本文采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
基于简书上的作品创作。 可转载、引用,但需经本人同意后署名作者且注明文章出处,并以相同方式共享。

知识共享许可协议
知识共享许可协议

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容