diff --git "a/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.19\344\272\213\345\212\241.md" "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.19\344\272\213\345\212\241.md" new file mode 100644 index 0000000000000000000000000000000000000000..addd3fa4f4118a9a5d1167874df37fe8af4ac708 --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.19\344\272\213\345\212\241.md" @@ -0,0 +1,75 @@ +#### 事务 + +#### 什么是事务 + +**事务( 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) 持久性 + +事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。 + +```sql +--创建account表 +create table account( +id varchar(20) primary key, +name nvarchar(20), +balance decimal(18,2) check(balance >=0) +) + +--创建account_detail表 +create table account_detail( +id varchar(20) primary key, +account_id varchar(20) foreign key references account(id), +amount decimal(18,2) check(amount >=0), +create_time datetime +) + +--插入account表数据 +insert into account values +('1','刘备',1000), +('2','关羽',2000), +('3','张飞',3000) +``` + +```sql +declare @my_error int=0 +begin transaction +-- 刘备准备消费3000元,如果刘备的账户余额足够,账户表就扣减3000元,并且往明细表写入一条消费记录 +-- 如果余额不足,那么消费不成功,余额不会扣减,也不会往明细表写入数据 +-- @@error 如果为0代表执行成功,如果失败的话@@error的值是不等于0的 +update account set balance=balance-100 where name='刘备' +set @my_error = @@error+@my_error +insert into account_detail VALUES('1','1',100,GETDATE()) +if @my_error =0 + begin + commit transaction + print '消费成功' + end +else + begin + rollback transaction + print '消费失败' + end +``` + +​ \ No newline at end of file diff --git "a/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.20\346\270\270\346\240\207.md" "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.20\346\270\270\346\240\207.md" new file mode 100644 index 0000000000000000000000000000000000000000..d0cb6cd2a52a207192a30965df3532fa52ef020c --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.20\346\270\270\346\240\207.md" @@ -0,0 +1,122 @@ +#### 游标 + +#### 什么是游标 + +游标(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 <游标名> +``` + +**关闭游标:** + +```sql +close <游标名> +``` + +**删除游标:** + +```sql +deallocate <游标名> +``` + + + +**提取数据操作:** + +```sql +fetch first from <游标名> --结果集的第一行 +fetch last from <游标名> --最后一行 +fetch absolute 1 from <游标名> --从游标的第一行开始数,第n行。(绝对值) +fetch relative 3 from <游标名> --提取从当前所在位置向下移动3行的数据。(相对值) +fetch next from <游标名> --当前位置的下一行 +fetch prior from <游标名> --当前位置的上一行 +``` + +**提取数据给变量以供它用(取出第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 <游标名> +``` + + + diff --git "a/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.21\345\207\275\346\225\260.md" "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.21\345\207\275\346\225\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..553c748b5ad077b4597ec2b641dd47e728dae699 --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.21\345\207\275\346\225\260.md" @@ -0,0 +1,119 @@ +#### 函数 + +函数分为(1)系统函数:,(2)自定义函数(方法:将一个功能封装成可重用的函数)。 + +其中自定义函数又可以分为(1)标量值函数(返回单个值),(2)表值函数(返回查询结果) + +本文主要介绍自定义函数的使用。 + +#### 标量值函数 + +语法结构: + +```sql +CREATE FUNCTION function_name(@parameter_name parameter_data_type) --(@参数名 参数的数据类型) +RETURNS date_type --返回返回值的数据类型 + +[WITH ENCRYPTION] --如果指定了 encryption 则函数被加密 + +[AS] + +BEGIN + + function_body --函数体 + + RETURN 表达式; + +END +例: +ALTER FUNCTION [dbo].[user_GetWhichDB] +( + @UserId INT = 0 +) +RETURNS TINYINT +WITH EXECUTE AS CALLER +AS +BEGIN + DECLARE @WhichDB TINYINT; + SET @WhichDB = 1; + IF @UserId >= 115098 + SET @WhichDB = 2; + + RETURN (@WhichDB); +END +``` + +定义函数要求实现: + +实现两个值的加和 + +使用函数求某门课的平均成绩 + + + +#### 表值函数 + +语法结构: + +```sql +create function 名称 + +([{@参数名称 参数类型[=默认值]}[,n]]) + +returns @局部变量 table(参数名 参数类型) + +[with encryption] + +[as] + +begin + +函数体 + +return 函数返回值 + +end +例: +CREATE FUNCTION fnSplit +( + @c VARCHAR(2000), + @split VARCHAR(2) +) +RETURNS @t TABLE(col VARCHAR(200)) +AS +BEGIN + WHILE (CHARINDEX(@split, @c) <> 0) + BEGIN + INSERT @t + ( + col + ) + VALUES + ( + SUBSTRING(@c, 1, CHARINDEX(@split, @c) -1) + ) + SET @c = STUFF(@c, 1, CHARINDEX(@split, @c), '') + END + INSERT @t + ( + col + ) + VALUES + ( + @c + ) + RETURN +END +GO + + +``` + + + +删除自定义函数 + +```sql +DROP function 函数名 +``` +