diff --git "a/23\346\236\227\344\270\226\346\266\233/\344\275\234\344\270\232/2022.09.30\344\275\234\344\270\232.sql" "b/23\346\236\227\344\270\226\346\266\233/\344\275\234\344\270\232/2022.09.30\344\275\234\344\270\232.sql" new file mode 100644 index 0000000000000000000000000000000000000000..ac9cff6a402bfeeb01467644c92763b6dcada7fb --- /dev/null +++ "b/23\346\236\227\344\270\226\346\266\233/\344\275\234\344\270\232/2022.09.30\344\275\234\344\270\232.sql" @@ -0,0 +1,49 @@ +--使用游标实现加薪操作 +declare huhu cursor scroll +for select * from People +open huhu +declare @PeopleId int +fetch first from huhu into @PeopleId +while (@@FETCH_STATUS=0) + begin + update People set PeopleSalary+=1000 where PeopleId=@PeopleId + fetch next from huhu into @PeopleId + end +close huhu +deallocate huhu +select * from People +--使用游标删除不达标员工 +declare huhu cursor scroll +for select * from People +open huhu +declare @id int +fetch first from huhu into @id +while (@@FETCH_STATUS=0) + begin + declare @money int=(select PeopleSalary from People where PeopleId=@id) + + if(@money<5000) + begin + delete People where PeopleId = @id + end + fetch next from huhu into @id + end +close huhu +deallocate huhu +select * from People +--使用游标 实现:如果A表与B表中ID字段值相同,那么将B表中的省份,城市 修改成与A表中的城市一致(连表) +declare cur_id cursor scroll +for select A.* from A inner join B on A.id = B.id +open cur_id +declare @id int , @id1 int,@Province varchar(10),@City varchar(10) +fetch first from cur_id into @id,@Province,@City +while(@@FETCH_STATUS = 0) + begin + update B set B.Province = @Province , B.City = @City where B.id = @id + fetch next from cur_id into @id,@Province,@City + end + +close cur_id +deallocate cur_id +select * from A +select * from B \ No newline at end of file diff --git "a/23\346\236\227\344\270\226\346\266\233/\347\254\224\350\256\260/2022.09.30\347\254\224\350\256\260.md" "b/23\346\236\227\344\270\226\346\266\233/\347\254\224\350\256\260/2022.09.30\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..618bee8d1bc5d865a7bf980d6daef2ae64a0dc46 --- /dev/null +++ "b/23\346\236\227\344\270\226\346\266\233/\347\254\224\350\256\260/2022.09.30\347\254\224\350\256\260.md" @@ -0,0 +1,322 @@ +## 回顾 + +- 使用索引可以加快数据访问速度. +- 两种类型的索引分别是聚集索引和非聚集索引. +- 使用CREATE INDEX可以为指定的表创建索引. +- 视图是一个虚表,通常用来查看数据库中一个或多个表的数据. +- 使用CREATE VIEW可以创建视图 + + + +## 事务 + + + +#### 什么是事务 + +**事务( Transaction)由一次或者多次基本操作构成,或者说,事务由一条或者多条 SQL 语句构成。** + +**事务中的所有 SQL 语句是一个整体,共同进退,不可分割,要么全部执行成功,要么全部执行失败。** + + + +#### 事务的属性(ACID) + +一般来说,事务具有四个标准属性,分别是原子性(**A**tomicity,或称不可分割性)、一致性(**C**onsistency)、隔离性(**I**solation,又称独立性)、持久性(**D**urability),简称 **ACID**。具体说明如下: + +##### 1) 原子性 + +一个事务中的所有 SQL 语句,要么全部执行成功,要么全部执行失败,不会结束在中间的某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。 + +##### 2) 一致性 + +在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的数据必须完全符合所有的预设规则,其中包含数据的精确度、串联性以及后续数据库可以自发性地完成预定的工作。 + +##### 3) 隔离性 + +数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。 死锁 操作系统 + +##### 4) 持久性 + +事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。 + + + +#### 事务执行流程 + +![](https://gitee.com/snailclass/tuchuang/raw/master/img/image-20220916113630148-2022-9-1611:40:42.png) + + + + + +#### 事务分类 + +**自动提交事物**: 是SQL Server默认的一种事务模式,每条Sql语句都被看成一个事务进行处理。 + +**显式事务**: T-sql标明,由Begin Transaction开启事务开始,由Commit Transaction 提交事务、Rollback Transaction 回滚事务结束。 + +**隐式事务**:使用Set IMPLICIT_TRANSACTIONS ON 将将隐式事务模式打开,不用Begin Transaction开启事务,当一个事务结束,这个模式会自动启用下一个事务,只用Commit Transaction 提交事务、Rollback Transaction 回滚事务即可。 + +TIPS: + +**事物回滚**: + +xact_abort on/off : 为on时如果当前sql出错,回滚整个事务,为off时如果sql出错回滚当前sql语句,其它语句照常运行读写数据库。 + + + + + + + +## 事务的隔离级别 + +#### 事务的ACID属性 + +​ Atomicity 原子性:同一个事务中的操作,要么全部成功,要么全部失败。 + +​ Consistency 一致性:数据库中的数据保证合法,满足所有的约束(比如唯一约束) + +​ Isolation **隔离性**:不同的事务不能相互影响 + +​ Durability 持久性:事务提交后,不管数据库是否崩溃重启,提交的事务所作出的修改都要生效 + +如果不对事务进行隔离,多个事务同时发生在数据库中,将会导致以下的问题: + +- **脏读**:一个事务读取到另一个未提交事务的修改。没保证原子性,如果当前事务基于这些脏数据进行操作,另一个事务回滚后,这些操作将会是错误的 +- **不可重复读**:事务中,另外的事务提交了update或delete,导致当前事务前后读取到的数据不一致。没保证持久性,会导致当前事务覆盖另外事务的修改 +- **幻读**:事务中,另外的事务提交了insert,导致当前事务前后读取到的数据总量不一致。当前事务先对唯一约束进行检查发现没有与将要插入的数据重复的,此时另外的事务提交了,导致当前事务进行插入后数据库中有两条相同的数据,破环了一致性 + +#### 事务的四种隔离级别 + +**read-uncommitted** **读未提交** + +​ 可以读到未提交的数据(完全不隔离) + +**read-committed 读已提交** + +​ 只能读取已提交的数据(避免脏读) + +**repeatable-read 可重复读** + +​ 只能读取到事务开始前,其它事务提交的数据(避免脏读、不可重复读) + +**serializable 串行化** + +​ 所有事务一个一个执行,不进行并发(避免脏读、不可重复读、幻读) + + + + + +```sql +--查看事务的隔离级别 +dbcc useroptions +--设置事务隔离级别 +set transaction isolation level <隔离级别> + +``` + + + + + + + + + + + + + +## 游标 + +#### 什么是游标 + +游标(Cursor)它使用户可逐行访问由SQL Server返回的结果集。使用游标(cursor)的一个主要的原因就是把集合操作转换成**单个记录处理方式**。用SQL语言从数据库中检索数据后,结果放在内存的一块区域中,且结果往往是一个含有多个记录的集合。游标机制允许用户在SQL server内逐行地访问这些记录,按照用户自己的意愿来显示和处理这些记录。 + +游标分类: + +(1)静态游标(Static):在操作游标的时候,数据发生变化,游标中数据不变 +(2)动态游标(Dynamic):在操作游标的时候,数据发生变化,游标中数据改变,默认值。 +(3)键集驱动游标(KeySet):在操作游标的时候,被标识的列发生改变,游标中数据改变,其他列改变,游标中数据不变。 + + + +#### 游标的使用 + +**创建游标:** + +```sql +--1.创建游标(Scroll代表滚动游标,不加Scroll则是只进的,只能支持fetch next) +declare <游标名> cursor scroll for select stuname from stuinfo +``` + +**打开游标:** + +```sql +open <游标名> +``` + +**关闭游标:** + +``` +close <游标名> +``` + +**释放游标:** + +``` +deallocate <游标名> +``` + + + +**提取数据操作:** + +```sql +fetch first from <游标名> --结果集的第一行 +fetch last from <游标名> --最后一行 +fetch absolute 1 from <游标名> --从游标的第一行开始数,第n行。 +fetch relative 3 from <游标名> --从当前位置数,第n行。 +fetch next from <游标名> --当前位置的下一行 +fetch prior from <游标名> --当前位置的上一行 +``` + +例1:使用游标输出部门编号为009的员工和工资 + +例2:使用游标输出各部门的部门号,最高工资,和最低工资 + +例3:使用游标实现加薪操作 + +例4:使用游标删除不达标员工 + + + + + + + +**提取数据给变量以供它用(取出第3行学生姓名,查询该学生详细信息):** + +```sql +declare @vari varchar(20) +fetch absolute 3 from <游标名> into @vari +select * from StuInfo where stuName = @vari +``` + +**利用游标提取所有的学生信息:** + +```sql +--方案一: +fetch absolute 1 from <游标名> +while @@FETCH_STATUS = 0 --@@FETCH_STATUS=0,提取成功,-1提取失败,-2行不存在 + begin + fetch next from <游标名> + end + +--方案二: +declare @myvar varchar(20) +fetch first from <游标名> into @myvar +while @@FETCH_STATUS = 0 + begin + print '提取成功'+@myvar + fetch next from <游标名> into @myvar + end +``` + +**利用游标修改和删除数据:** + +```sql +--更新语法: +-- fetch absolute 3 from <游标名> +-- update 语句 where Current of <游标名> + + +--练习1:修改周飘的班级id为1 + +--练习2:使用删除姓名为曾鹏的个人信息 + +``` + +**创建游标指向某行多列数据,并循环显示数据:** + +```sql +--此处如果指向所有数据,可以将for后面的语句修改成select * from stuinfo +declare <游标名> cursor scroll +declare mycursor cursor scroll for select stuname,StuSex,ClassID from stuinfo + +open <游标名> + +declare @name varchar(20) +declare @sex varchar(2) +declare @cid int +fetch first from mycursor into @name,@sex,@cid +while @@FETCH_STATUS=0 +fetch next from <游标名> into into @name,@sex,@cid + +while @@FETCH_STATUS = 0 --@@FETCH_STATUS=0,提取成功,-1提取失败,-2行不存在 + begin + print '提取成功' + fetch next from CURSORMember into@into @name,@sex,@cid + end +close <游标名> +``` + + + +## 练习 + +**事务练习(BankTest):** + + + +1.--假设刘备取款6000,(添加check约束,设置账户余额必须>=0),要求:使用事务实现,修改余额和添加取款记录两步操作使用事务 + +2.--刘备向张飞转账1000元,(添加check约束,设置账户余额必须>=0) + +![](https://gitee.com/snailclass/tuchuang/raw/master/img/image-20220916113716667-2022-9-1611:40:44.png) + + + +**游标练习** + +- 创建学生游标,该游标包含(学生姓名,兴趣爱好,生源地,荣誉总数) +- 循环遍历161开头的学生信息 +- 使用游标统计生源地为北京的荣誉总数 + +2. + +```sql +create table A( + id int primary key, + Province varchar(20), + City varchar(20) +) + +create table B( + id int primary key, + Province varchar(20), + City varchar(20) +) + +insert into A values(1,'福建','厦门') +insert into A values(2,'广东','广州') +insert into A values(3,'福建','龙岩') +insert into A values(4,'云南','昆明') + +insert into B values(1,'江西','南昌') +insert into B values(3,'江苏','南京') +insert into B values(5,'湖北','武汉') +insert into B values(7,'湖南','长沙') +``` + +要求:使用游标 实现:如果A表与B表中ID字段值相同,那么将B表中的省份,城市 修改成与A表中的城市一致(连表) + + + +结果: + +![](https://gitee.com/snailclass/tuchuang/raw/master/img/1664467173765-2022-9-3000:00:30.png) +