diff --git "a/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.19\344\275\234\344\270\232.md" "b/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.19\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..e21592f23f24c0d85c366827a33d16d243ad6211 --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.19\344\275\234\344\270\232.md" @@ -0,0 +1,56 @@ +1.--假设刘备取款6000,(添加check约束,设置账户余额必须>=0),要求:使用事务实现,修改余额和添加取款记录两步操作使用事务 + +```sql +begin transaction +declare @mon money = 6000 +declare @n varchar(20) +declare @er int = 0 + +select @n =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 @er += @@ERROR +insert CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime) values(@n,0,@mon,getdate()) + + +if @er>0 + begin + print '事务提交失败' + rollback transaction + end +else + begin + print '事务提交成功' + commit transaction + end +``` + +2.--刘备向张飞转账1000元,(添加check约束,设置账户余额必须>=0) + +```sql +begin transaction + declare @myerr int = 0 + declare @CardNo1 varchar(200),@CardNo2 varchar(200),@money money = 1000 + select @CardNo1= CardNo from BankCard where AccountId = (select AccountId from AccountInfo where RealName='刘备') + select @CardNo2= CardNo from BankCard where AccountId = (select AccountId from AccountInfo where RealName='张飞') + update BankCard set CardMoney = CardMoney-@money where AccountId = (select AccountId from AccountInfo where RealName='刘备') + set @myerr = @myerr + @@ERROR + update BankCard set CardMoney = CardMoney+@money where AccountId = (select AccountId from AccountInfo where RealName='张飞') + set @myerr = @myerr + @@ERROR + --银行卡交易记录 + insert CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime) values(@CardNo1,0,1000,GETDATE()) + insert CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime) values(@CardNo2,1000,0,GETDATE()) + --转账记录 + insert CardTransfer(CardNoOut,CardNoIn,TransferMoney,TransferTime) values(@CardNo1,@CardNo2,@money,GETDATE()) + +if @myerr = 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/\344\275\234\344\270\232/9.26\344\275\234\344\270\232.md" "b/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.26\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..7ebd566c2bfb4a1f67003c2c8b3cd10d719930e5 --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.26\344\275\234\344\270\232.md" @@ -0,0 +1,33 @@ +--1. 定义存储过程实现查询出账户余额最低的银行卡账户信息,显示银行卡号,姓名,账户余额 +create proc proc_MinMoneyCard +as + select top 1 CardNo 银行卡号,RealName 姓名,CardMoney 余额 + from BankCard inner join AccountInfo on BankCard.AccountId = AccountInfo.AccountId + order by CardMoney asc +go +exec proc_MinMoneyCard +--2. 模拟银行卡存钱操作,传入银行卡号,存钱金额,实现存钱操作 +create proc proc_CunQian +@CardNo varchar(30), +@MoneyInBank money +as + update BankCard set CardMoney = CardMoney + @MoneyInBank where CardNo = @CardNo + insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime) + values(@CardNo,@MoneyInBank,0,GETDATE()) +go +exec proc_CunQian '6225125478544587',3000 +--3. 模拟银行卡取钱操作,传入银行卡号,取钱金额,实现取钱操作,取钱成功,返回1,取钱失败返回-1 +create proc proc_QuQian +@CardNo varchar(30), +@MoneyOutBank money +as + update BankCard set CardMoney = CardMoney - @MoneyOutBank where CardNo = @CardNo + if @@ERROR <> 0 + return -1 + insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime) + values(@CardNo,0,@MoneyOutBank,GETDATE()) + return 1 +go +declare @returnValue int +exec @returnValue = proc_QuQian '662018092100000002',1000000 +print @returnValue \ No newline at end of file diff --git "a/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.27\344\275\234\344\270\232.md" "b/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.27\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..e4f0f1e4210cd1cbd91b9a39cf3b44119142b030 --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.27\344\275\234\344\270\232.md" @@ -0,0 +1,61 @@ +--(1)假设有部门表和员工表,在添加员工的时候,该员工的部门编号如果在部门表中找不到,则自动添加部门信息,部门名称为"新部门"。 + +```sql +create trigger tri_a on people +after insert +as +begin + declare @A varchar(20),@B varchar(20) + select @A=DepartmentId from inserted + select @B='新部门' + insert into Department values(@A,@B) + end +insert into People +values('009','赵云','男','666') +``` + +--(2)触发器实现,删除一个部门的时候将部门下所有员工全部删除。 + +```sql +create trigger tri_De on Department +after delete +as +begin + declare @q varchar(20) + select @q=DepartmentId from deleted + delete from People where DepartmentId=@q + end + +delete from Department where DepartmentId = '001' +``` + +(3)创建一个触发器,删除一个部门的时候判断该部门下是否有员工,有则不删除,没有则删除。 + +```sql +create trigger tri_De on Department +Instead of delete +as + begin + declare @z varchar(20),@B int + select @z=DepartmentId from deleted + select @B=COUNT(DepartmentId) from People where Departmentid=@z + if @B=0 + begin + delete from Department where DepartmentName=@z + end + end +delete Department where DepartmentId = '001' +``` + +(4)修改一个部门编号之后,将该部门下所有员工的部门编号同步进行修改 + +```sql +create trigger tri_Update on Department +after update +as + update People set DepartmentId = (select DepartmentId from inserted) + where DepartmentId = (select DepartmentId from deleted) +go +update Department set DepartmentId = '003' where DepartmentId='001' +``` + diff --git "a/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.7\344\275\234\344\270\232.md" "b/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.7\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..c32835a61670d65de0fa7015968557809a549a48 --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\344\275\234\344\270\232/9.7\344\275\234\344\270\232.md" @@ -0,0 +1,84 @@ +#### 1. 关羽的银行卡号为"6225547858741263",查询出余额比关羽多的银行卡信息,显示卡号,身份证,姓名,余额。 + +```sql +declare @g money +select @g= CardMoney from BankCard where CardNo='6225547858741263' +print @g + +select CardNo,AccountCode,RealName,CardMoney from BankCard bc +inner join AccountInfo ac on bc.AccountId=ac.AccountId +where CardMoney>@g +``` + +#### --2. 从所有账户信息中查询出余额最高的交易明细(存钱取钱信息)。 + +```sql +select ce.* from CardExchange ce +inner join BankCard ba on ce.CardNo=ba.CardNo +where CardMoney=(select max(CardMoney) from BankCard) +``` + +#### --3. 查询有取款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额。 + +```sql +select ca.CardNo 卡号,accountCode 身份证,realname 姓名,cardmoney 余额 from CardExchange ca +inner join BankCard bc on ca.CardNo=bc.CardNo +inner join AccountInfo ac on bc.AccountId=ac.AccountId +where MoneyOutBank>0 +``` + +#### --4. 查询出没有存款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额。 + +```sql +select CardNo ,AccountCode,RealName,CardMoney +from BankCard +left join AccountInfo on AccountInfo.AccountId=BankCard.AccountId +where CardNo not in(select CardNo from CardExchange where MoneyInBank>0) +``` + +#### --5. 关羽的银行卡号为"6225547858741263",查询当天是否有收到转账。 + +```sql +declare @g varchar(20)='6225547858741263' +declare @c varchar(20) + +select @c=CardNoIn from CardTransfer +where @g=any(select CardNoIn from CardTransfer) + +if @c is null +begin +print '无转账' +end +else +begin +print '有转账' +end +``` + +#### --6. 查询出交易次数(存款取款操作)最多的银行卡账户信息,显示:卡号,身份证,姓名,余额,交易数。 + +```sql +select ba.CardNo,AccountCode,RealName,CardMoney,count(ca.CardNo) 交易数 from CardExchange ca + +inner join BankCard ba on ba.CardNo = ca.CardNo +inner join AccountInfo ac on ac.AccountId = ba.AccountId + +where ca.CardNo=( + select top 1 CardExchange.CardNo from CardExchange + group by CardExchange.CardNo + order by count(CardExchange.CardNo) desc +) +group by ca.CardNo,ba.CardNo,AccountCode,RealName,CardMoney +``` + +#### --7. 查询出没有转账交易记录的银行卡账户信息,显示卡号,身份证,姓名,余额。 + +```sql +select CardNo,AccountCode,RealName,CardMoney +from BankCard +join AccountInfo on AccountInfo.AccountId = BankCard.AccountId + +where BankCard.CardNo!=all(select CardNoIn from CardTransfer) + +and BankCard.CardNo!=all(select CardNoOut from CardTransfer) +``` \ 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.22\346\255\273\351\224\201.md" "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.22\346\255\273\351\224\201.md" new file mode 100644 index 0000000000000000000000000000000000000000..311aa214c2eb8709ec2138744ab54fd98c6179dc --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.22\346\255\273\351\224\201.md" @@ -0,0 +1,20 @@ +#### 死锁 + + **1.** **死锁原理** + + 根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。 + + 死锁的四个必要条件: +互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。 +请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。 +非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。 +循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。 + + 说明:T1、T2表示两个任务;R1和R2表示两个资源;由资源指向任务的箭头(如R1->T1,R2->T2)表示该资源被改任务所持有;由任务指向资源的箭头(如T1->S2,T2->S1)表示该任务正在请求对应目标资源; + 其满足上面死锁的四个必要条件: +(1).互斥:资源S1和S2不能被共享,同一时间只能由一个任务使用; +(2).请求与保持条件:T1持有S1的同时,请求S2;T2持有S2的同时请求S1; +(3).非剥夺条件:T1无法从T2上剥夺S2,T2也无法从T1上剥夺S1; +(4).循环等待条件:上图中的箭头构成环路,存在循环等待。 + + \ 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.26\345\255\230\345\202\250.md" "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.26\345\255\230\345\202\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..c0b47c5fe1093f772294ad1dc12e484ef4aafd03 --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.26\345\255\230\345\202\250.md" @@ -0,0 +1,120 @@ +#### 存储 + +#### 什么是存储过程 + +存储过程是**预编译**SQL语句集合,这些语句存储在一个名称(存储过程的名称)下并作为单元来处理。存储过程代替了传统的逐条执行SQL语句的方式,一个存储过程中可以包含查询、插入、删除、更新等操纵的一系列SQL语句,当这个存储过程被调用执行时,这些操作也会同时执行。 + +封装好 --> 调用 + +#### 存储过程的分类 + +##### 系统存储过程 + + 系统存储过程是用来管理SQL Server与显示有关数据库和用户的信息的存储过程。 + +常见的系统存储过程有 + +```sql +sp_databases 列出服务上的所有数据库 +sp_helpdb --报告有关指定数据库或所有数据库的信息 +sp_renamedb 更改数据库的名称 +sp_tables --返回当前环境下可查询的对象的列表 +sp_columns 返回某个表列的信息 +sp_help --返回某个表的所有信息 +sp_helpconstraint 查看某个表的约束 +sp_helpindex --查看某个表的索引 +sp_stored_procedures 列出当前环境中的所有存储过程 +sp_password --添加或修改登录账户的密码 +sp_rename 重命名存储过程 +sp_helptext 显示默认值,未加密的存储过程、用户定义的存储过程、触发器或视图的实际文本。 +``` + + + +##### 自定义存储过程 + +**创建存储过程** + +1.没有输入参数,没有输出参数的存储过程。 + +```sql +create proc <存储过程名称> +as + +go +``` + +练习: 定义存储过程查询 年龄最小的学生信息 + +2.有输入参数,没有输出参数的存储过程 + +```sql +create proc <存储过程名称> +<变量1> <数据类型> +<变量2> <数据类型> +... +as + +go +``` + + + + + +3.有输入参数,没有输出参数,但是有返回值的存储过程(返回值必须整数)。 + +```sql +create proc <存储过程名称> +<变量1> <数据类型> +<变量2> <数据类型> +... +as + +return 整数 +go +``` + + + +4.有输入参数,有输出参数的存储过程 & 一个变量具备同时输入输出参数的存储过程 + +```sql +create proc <存储过程名称> +<变量1> <数据类型> output +<变量2> <数据类型> output +... +as + +return 整数 +go +``` + + + +**执行存储过程** + +```sql +--无参 +exec <存储过程名称> +--带参 +exec <存储过程名称> <形参1>,<形参2>,... +--带参带返回值 +declare @变量 +exec @变量 = <存储过程名称> <形参1>,<形参2>,... +--有输入参数,有输出参数的存储过程 +declare @变量 +exec <存储过程名称> <形参1>,<形参2>,@变量 output +--一个变量同时具备输入输出功能 +declare @变量 <数据类型> = 值 +exec <存储过程名称> <形参1>,<形参2>,@变量 output +``` + + + +**删除存储过程** + +```sql +drop procedure <存储过程名称> +``` + diff --git "a/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.27\350\247\246\345\217\221\345\231\250.md" "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.27\350\247\246\345\217\221\345\231\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..e9ee6801c49d04913be87e96a3b886030dd62b4a --- /dev/null +++ "b/22\346\235\216\351\233\205\350\212\270/\347\254\224\350\256\260/9.27\350\247\246\345\217\221\345\231\250.md" @@ -0,0 +1,129 @@ +#### 触发器 + +#### 什么是触发器 + + **触发器**( trigger )是作为**对数据库修改的连带效果**而**由系统自动执行**的一条语句。它是一种特殊的**存储过程**。也是一个**事务**(可以回滚)。为了定义一个[触发器](https://so.csdn.net/so/search?q=触发器&spm=1001.2101.3001.7020),我们必须: + +- 指明**什么时候执行触发器**。这被拆分为**引起触发器被检测的一个\*事件\***和**触发器继续执行所必须满足的一个条件**。 +- 指明**当触发器执行时所采取的动作**。 + + + +#### 触发器分类 + +分为 DML触发器和DDL触发器 + +#### DML触发器 : 增删改 + +##### after触发器(之后触发) + +after触发器主要用于:insert(增加),update(修改),delete(删除) + +##### instead of 触发器 (之前触发) + + + +#### 创建触发器的语句 + +```sql +CREATE TRIGGER <触发器名称> + +ON 表格名 + +[WITH ENCRYPTION] + +FOR [DELETE, INSERT, UPDATE] + +AS + + T-SQL语句 + +GO +--WITH ENCRYPTION表示加密触发器定义的SQL文本 + +--DELETE, INSERT, UPDATE指定触发器的类型 +``` + +##### 插入触发器 + +```sql +--GradeInfo表中插入一条数据,MyStudentInfo表中插入一条记录 +IF (object_id('tr_insert','tr') is not null) + drop trigger tr_insert +GO +CREATE trigger tr_insert +on GradeInfo +after insert --插入触发 +as + begin + --定义变量 + declare @GradeId int + --在inserted表中查询已经插入记录信息 + select @GradeId=id from INSERTED + --MyStudentInfo表中插入数据 + insert INTO MyStudentInfo (GradeId) VALUES (@GradeId) + print '插入成功!' + end + +``` + +插入数据 + +```sql +insert INTO GradeInfo VALUES(11,'C++') +``` + +删除 + +```sql +--删除MyStudentInfo表中的数据,插入备份表 + IF (object_id('tr_Delete','tr') is not null) + drop TRIGGER tr_Delete + GO + CREATE trigger tr_Delete + on MyStudentInfo + for delete + as + begin + print '正在备份数据......' + IF (object_id('MyStudentInfo_Back','U') is not null) + --存在表,直接插入数据 + insert INTO MyStudentInfo_Back SELECT * from DELETED + else + select * into MyStudentInfo_Back from DELETED + PRINT '备份完成' + end + +``` + +修改 + +```sql +IF (object_id('tr_Update','tr') is not null) + drop TRIGGER tr_Update + GO + CREATE trigger tr_Update + on MyStudentInfo + for update + as + begin + --声明变量,存储更新前和更新后的姓名 + declare @OldName varchar(16),@NewName varchar(16) + select @OldName=name from DELETED + print '更新前姓名:'+@OldName + select @NewName=name from INSERTED + print '更新后姓名:'+@NewName +end +``` + +## 总结 + + 1.插入操作(Insert) +***\*inserted 表\****有数据,***\*deleted 表\****无数据 + +2.删除操作(Delete) +***\*inserted 表\****无数据,***\*deleted 表\****有数据 + +3.更新操作(Update) +***\*inserted 表\****有数据(新数据),***\*deleted 表\****有数据(旧数据) +