From d014b492aa4061b91c93b99dce62ecb52f46898a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=AB=E6=99=A8=E7=BE=BF?= <1004864698@qq.com> Date: Wed, 21 Sep 2022 13:00:03 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../9.19.\344\272\213\345\212\241.md" | 74 +++++++++++++++++ .../9.20.\346\270\270\346\240\207.md" | 79 +++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 "47\345\267\253\346\231\250\347\276\277/sql\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\254\224\350\256\260/9.19.\344\272\213\345\212\241.md" create mode 100644 "47\345\267\253\346\231\250\347\276\277/sql\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\254\224\350\256\260/9.20.\346\270\270\346\240\207.md" diff --git "a/47\345\267\253\346\231\250\347\276\277/sql\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\254\224\350\256\260/9.19.\344\272\213\345\212\241.md" "b/47\345\267\253\346\231\250\347\276\277/sql\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\254\224\350\256\260/9.19.\344\272\213\345\212\241.md" new file mode 100644 index 0000000..b7ef472 --- /dev/null +++ "b/47\345\267\253\346\231\250\347\276\277/sql\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\254\224\350\256\260/9.19.\344\272\213\345\212\241.md" @@ -0,0 +1,74 @@ +# 事务 + +### 事务的属性(ACID) + +一般来说,事务具有四个标准属性,分别是原子性(**A**tomicity,或称不可分割性)、一致性(**C**onsistency)、隔离性(**I**solation,又称独立性)、持久性(**D**urability),简称 **ACID**。具体说明如下: + +#### 1. 原子性 + +一个事务中的所有 SQL 语句,要么全部执行成功,要么全部执行失败,不会结束在中间的某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。 + +#### 2.一致性 + +在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的数据必须完全符合所有的预设规则,其中包含数据的精确度、串联性以及后续数据库可以自发性地完成预定的工作。 + +#### 3.隔离性 + +数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。 死锁 操作系统 + +#### 4. 持久性 + +事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。 + +## 事务练习 + +```sql +1.--假设刘备取款6000,(添加check约束,设置账户余额必须>=0),要求:使用事务实现,修改余额和添加取款记录两步操作使用事务 +begin transaction +declare @mon money = 6000 +declare @no varchar(20) +declare @err int = 0 --一开始所有语句都没有错误 +select @no = cardno from BankCard where AccountId=(select AccountId from AccountInfo where RealName='刘备') +update BankCard set CardMoney=CardMoney-@mon where AccountId=(select AccountId from AccountInfo where RealName='刘备') +set @err += @@ERROR +insert CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime) values(@no,0,@mon,getdate()) +if @err>0 + begin + print '事务提交失败' + rollback transaction + end +else + begin + print '事务提交成功' + commit transaction + end +2.--刘备向张飞转账1000元,(添加check约束,设置账户余额必须>=0) +begin transaction +declare @zf char(18) +declare @lb char(18) +declare @err int = 0 +declare @money int = 1000 +select @lb = CardNo from AccountInfo ao +inner join BankCard bd on ao.AccountId=bd.AccountId +where RealName='刘备' +select @zf = CardNo from AccountInfo ao +inner join BankCard bd on ao.AccountId=bd.AccountId +where RealName='张飞' +alter table BankCard add constraint ck_Cardmoney check(cardmoney>=0) +UPDATE BankCard SET CardMoney=CardMoney-@money where CardNo=@lb +UPDATE BankCard SET CardMoney=CardMoney+@money where CardNo=@zf +set @err += @@ERROR +insert CardTransfer values(@lb,@zf,@money,GETDATE()) +insert CardExchange values(@lb,0,@money,GETDATE()) +insert CardExchange values(@zf,@money,0,GETDATE()) +if @err>0 + begin + print '转账失败' + rollback transaction + end +else + begin + print '转账成功' + commit transaction + end +``` \ No newline at end of file diff --git "a/47\345\267\253\346\231\250\347\276\277/sql\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\254\224\350\256\260/9.20.\346\270\270\346\240\207.md" "b/47\345\267\253\346\231\250\347\276\277/sql\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\254\224\350\256\260/9.20.\346\270\270\346\240\207.md" new file mode 100644 index 0000000..e7bcda3 --- /dev/null +++ "b/47\345\267\253\346\231\250\347\276\277/sql\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241\347\254\224\350\256\260/9.20.\346\270\270\346\240\207.md" @@ -0,0 +1,79 @@ +# 游标 + +##### 含义: + +游标(**Cursor**)它使用户可逐行访问由**SQL** Server返回的结果集。使用游标(**cursor**)的一个主要的原因就是把集合操作转换成**单个记录处理方式**。用**SQL**语言从数据库中检索数据后,结果放在内存的一块区域中,且结果往往是一个含有多个记录的集合。游标机制允许用户在**SQL** server内逐行地访问这些记录,按照用户自己的意愿来显示和处理这些记录。 + +缺点:使用游标会把结果集一条条取出来处理,增加了服务器的负担,再者使用游标的效率远远没有使用默认结果集的效率高。所以,能不用游标就尽量不要用。 + +##### 分类: + +(1)静态游标(**Static**):在操作游标的时候,数据发生变化,游标中数据不变 + +(2)动态游标(**Dynamic**):在操作游标的时候,数据发生变化,游标中数据改变,默认值。 + +(3)键集驱动游标(KeySet):在操作游标的时候,被标识的列发生改变,游标中数据改变,其他列改变, 游标中数据不变。 + +##### 使用: + +1、创建游标 + +(**Scroll**代表滚动游标,不加**Scroll**则是只进的,只能支持**fetch** **next**) + +**declare** <游标名> **cursor** **scroll** **for** **select** stuname **from** stuinfo + +2、打开游标 + +**open** <游标名> + +3、删除游标 + +**deallocate** <游标名> + +4、关闭游标 + +**close** <游标名> + +提取数据操作 + +**fetch** **first** **from** <游标名> --结果集的第一行 + +**fetch** **last** **from** <游标名> --最后一行 + +**fetch** **absolute** 1 **from** <游标名> --从游标的第一行开始数,第n行。 + +**fetch** **relative** 3 **from** <游标名> --从当前位置数,第n行。 + +**fetch** **next** **from** <游标名> --当前位置的下一行 + +**fetch** **prior** **from** <游标名> --当前位置的上一行 + +##### 例子 + +1.提取数据给变量以供它用(取出第3行学生姓名,查询该学生详细信息): + +**declare** @vari varchar(20) + +**fetch** **absolute** 3 **from** <游标名> **into** @vari + +**select** * **from** StuInfo **where** stuName = @vari + +2.创建游标指向某行多列数据,并循环显示数据: + +**declare** @id int,@name varchar(20),@sex varchar(2),@cid int + +**declare** mycursor **cursor** **for**(**select** * **from** StuInfo) + +**open** mycursor + +while @@FETCH_STATUS = 0 --@@FETCH_STATUS=0,提取成功,-1提取失败,-2行不存在 + +​ begin + +​ print **convert**(varchar(20),@id)+','+@name+','+@sex+','+**cast**(@cid **as** varchar(10)) + +​ **fetch** **next** **from** mycursor **into** @id,@name,@sex,@cid + +​ end + +**close** mycursor \ No newline at end of file -- Gitee