From bd77dcec3d7420b3ca5b581308d9d11c1364a4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E9=9D=99?= <3532970268@qq.com> Date: Mon, 26 Sep 2022 23:30:08 +0800 Subject: [PATCH] =?UTF-8?q?=E9=BA=BB=E8=BE=A3=E6=AF=9B=E8=9B=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...06\345\233\276\344\275\234\344\270\232.md" | 13 + ...07\347\250\213\344\275\234\344\270\232.md" | 57 ++++ ...55\345\217\245\344\275\234\344\270\232.md" | 66 +++++ ...45\350\257\242\344\275\234\344\270\232.md" | 57 ++++ .../9.20--\346\270\270\346\240\207.md" | 260 ++++++++++++++++++ ...32\344\271\211\345\207\275\346\225\260.md" | 195 +++++++++++++ .../9.22--\346\255\273\351\224\201.md" | 82 ++++++ ...30\345\202\250\350\277\207\347\250\213.md" | 145 ++++++++++ 8 files changed, 875 insertions(+) create mode 100644 "38\345\274\240\351\235\231/\344\275\234\344\270\232/9.15--\350\247\206\345\233\276\344\275\234\344\270\232.md" create mode 100644 "38\345\274\240\351\235\231/\344\275\234\344\270\232/9.26--\345\255\230\345\202\250\350\277\207\347\250\213\344\275\234\344\270\232.md" create mode 100644 "38\345\274\240\351\235\231/\344\275\234\344\270\232/9.6--\351\200\273\350\276\221\350\257\255\345\217\245\344\275\234\344\270\232.md" create mode 100644 "38\345\274\240\351\235\231/\344\275\234\344\270\232/9.7--\345\255\220\346\237\245\350\257\242\344\275\234\344\270\232.md" create mode 100644 "38\345\274\240\351\235\231/\347\254\224\350\256\260/9.20--\346\270\270\346\240\207.md" create mode 100644 "38\345\274\240\351\235\231/\347\254\224\350\256\260/9.21--\350\207\252\345\256\232\344\271\211\345\207\275\346\225\260.md" create mode 100644 "38\345\274\240\351\235\231/\347\254\224\350\256\260/9.22--\346\255\273\351\224\201.md" create mode 100644 "38\345\274\240\351\235\231/\347\254\224\350\256\260/9.26--\345\255\230\345\202\250\350\277\207\347\250\213.md" diff --git "a/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.15--\350\247\206\345\233\276\344\275\234\344\270\232.md" "b/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.15--\350\247\206\345\233\276\344\275\234\344\270\232.md" new file mode 100644 index 0000000..9de99fa --- /dev/null +++ "b/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.15--\350\247\206\345\233\276\344\275\234\344\270\232.md" @@ -0,0 +1,13 @@ +编写视图实现查询出所有银行卡账户信息,显示卡号,身份证,姓名,余额。 + +```sql +--1)编写视图实现查询出所有银行卡账户信息,显示卡号,身份证,姓名,余额。 +create view vw_aban(显示卡号,身份证,姓名,余额) +as +select CardNo,AccountCode,RealName,CardMoney from AccountInfo a +join BankCard b on a.AccountId=b.AccountId +go +select * from vw_aban + +drop view vw_aban +``` \ No newline at end of file diff --git "a/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.26--\345\255\230\345\202\250\350\277\207\347\250\213\344\275\234\344\270\232.md" "b/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.26--\345\255\230\345\202\250\350\277\207\347\250\213\344\275\234\344\270\232.md" new file mode 100644 index 0000000..d277f72 --- /dev/null +++ "b/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.26--\345\255\230\345\202\250\350\277\207\347\250\213\344\275\234\344\270\232.md" @@ -0,0 +1,57 @@ +--1. 定义存储过程实现查询出账户余额最低的银行卡账户信息,显示银行卡号,姓名,账户余额 + +```SQL +create proc proc_min +as +select top 1 cardno,RealName,CardMoney from AccountInfo a +join BankCard b on a.AccountId=b.AccountId +order by CardMoney +go + +exec proc_min +``` + +--2. 模拟银行卡存钱操作,传入银行卡号,存钱金额,实现存钱操作 + +```sql +create proc proc_inbank +@no varchar(20),@money money +as +update BankCard set CardMoney=CardMoney+@money where CardNo=@no +insert CardExchange values(@no,@money,0,GETDATE()) +go + +exec proc_inbank '6225125478544587',500 +``` + +--3. 模拟银行卡取钱操作,传入银行卡号,取钱金额,实现取钱操作,取钱成功,返回1,取钱失败返回-1 + +```sql +create proc proc_outbank +@no varchar(20),@money money +as +declare @moneys money +select @moneys=CardMoney from BankCard where CardNo=@no +if(@moneys<=0) +begin +return -1 +end +else +begin +update BankCard set CardMoney=CardMoney-@money where CardNo=@no +insert CardExchange values(@no,0,@money,GETDATE()) +return 1 +end +go + +declare @i int +exec @i= proc_outbank '6225125478544587',500 +print @i +``` + +--4. 查询出某时间段的银行存取款信息以及存款总金额,取款总金额, +--传入开始时间,结束时间,显示存取款交易信息的同时,返回存款总金额,取款总金额。 + +5.**密码升级**,传入用户名和密码,如果用户名密码正确,并且密码长度<8,自动升级成8位密码 + +(提示:随机生成 0-9 的整数: float(rand()*10)) rand():随机生成0.0-1.0的小数 float:向下取整) \ No newline at end of file diff --git "a/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.6--\351\200\273\350\276\221\350\257\255\345\217\245\344\275\234\344\270\232.md" "b/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.6--\351\200\273\350\276\221\350\257\255\345\217\245\344\275\234\344\270\232.md" new file mode 100644 index 0000000..380663c --- /dev/null +++ "b/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.6--\351\200\273\350\276\221\350\257\255\345\217\245\344\275\234\344\270\232.md" @@ -0,0 +1,66 @@ +-练习:在 StuScore 表中如果学生的平均成绩没有达到80分,便给每位同学的数学成绩加1分,然后再次判断平均成绩是否达到80分, --否则继续加分,这样反复加分,直到其平均成绩超过80分 + +```sql +while(1=1) +begin + declare @j int + select @j=AVG(Chinese+English+Math) from StuScore + print @j //226 + if(@j<=80) + update StuScore set Math=Math+1 + else + break +end +``` + +--1. 为赵云此人进行开户开卡操作,赵云身份证:420107199904054233 + +```sql +declare @cno varchar(30)='420107199904054233' +insert AccountInfo values(@cno,'13542265123','赵云',getdate()) +insert BankCard values('6223695231569457',4,123456,0.00,1,getdate()) +``` + +--2. 需要求出张飞的银行卡卡号和余额,张飞身份证: (1.使用连接查询,2.使用变量) + +```sql +declare @ano varchar(20)='420107199602034138 ' +select CardNo,CardMoney from AccountInfo a +join BankCard b on a.AccountId=b.AccountId +where AccountCode= @ano +``` + +-- 3.某用户银行卡号为“6225547854125656”,该用户执行取钱操作,取钱5000元,余额充足则进行取钱操作,并提示"取钱成功",否则提示“余额不足”。 + +```sql +declare @balance money +select @balance = (select CardMoney from BankCard where CardNo='6225547854125656') +if @balance >= 5000 + begin + update BankCard set CardMoney = CardMoney - 5000 + insert into CardExchange(CardNo,MoneyInBank,MoneyOutBank,ExchangeTime) + values('6225547854125656',0,5000,GETDATE()) + end +else + print '余额不足' +``` + +-- 条件分支:case-when + +-- 4.查询银行卡信息,将银行卡状态1,2,3,4分别转换为汉字“正常,挂失,冻结,注销”,并且根据银行卡余额显示银行卡等级 30万以下为“普通用户”,30万及以上为"VIP用户", ----显示列分别为卡号,身份证,姓名,余额,用户等级,银行卡状态。 + +```sql +select CardNo ,AccountCode ,RealName ,CardMoney ,CardState, +case +when CardState='1' then '正常' +when CardState='2' then '挂失' +when CardState='3' then '冻结' +when CardState='4' then '注销' +end 银行卡状态, +case +when CardMoney >=300000 then 'VIP用户' +when CardMoney <300000 then '普通用户' +end 用户等级 +from BankCard b +join AccountInfo a on b.AccountId=a.AccountId +``` \ No newline at end of file diff --git "a/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.7--\345\255\220\346\237\245\350\257\242\344\275\234\344\270\232.md" "b/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.7--\345\255\220\346\237\245\350\257\242\344\275\234\344\270\232.md" new file mode 100644 index 0000000..4d9569e --- /dev/null +++ "b/38\345\274\240\351\235\231/\344\275\234\344\270\232/9.7--\345\255\220\346\237\245\350\257\242\344\275\234\344\270\232.md" @@ -0,0 +1,57 @@ +1. 关羽的银行卡号为"6225547858741263",查询出余额比关羽多的银行卡信息,显示卡号,身份证,姓名,余额。 + +```sql +select CardNo,AccountCode,RealName,CardMoney from AccountInfo a +join BankCard b on a.AccountId=b.AccountId +where CardMoney >any (select CardMoney from BankCard where CardNo='6225547858741263') +``` + +2. 从所有账户信息中查询出余额最高的交易明细(存钱取钱信息)。 + +```sql +select * from CardExchange where MoneyInBank =(select max(MoneyInBank) from CardExchange) +and MoneyOutBank =(select max(MoneyOutBank) from CardExchange) +``` + +3. 查询有取款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额。 + +```sql +select CardNo,AccountCode,RealName,CardMoney from AccountInfo a +join BankCard b on a.AccountId=b.AccountId +where CardNo in(select cardno from CardExchange where MoneyOutBank is not null) +``` + +4. 查询出没有存款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额。 + +```sql +select CardNo,AccountCode,RealName,CardMoney from AccountInfo a +join BankCard b on a.AccountId=b.AccountId +where CardNo in(select cardno from CardExchange where MoneyInBank is null) +``` + +5. 关羽的银行卡号为"6225547858741263",查询当天是否有收到转账。 + +```sql +if exists(select * from CardTransfer where TransferTime=getdate() and CardNoOut='6225547858741263') +print '有收账' +else +print '无收账' +``` + +6. 查询出交易次数(存款取款操作)最多的银行卡账户信息,显示:卡号,身份证,姓名,余额,交易数。 + +```sql +select top 1 b.CardNo,AccountCode,RealName,CardMoney,交易次数 from AccountInfo a +join BankCard b on a.AccountId=b.AccountId +join (select CardNo,count(*) 交易次数 from CardExchange group by CardNo +) ta on b.CardNo=ta.CardNo +order by 交易次数 desc +``` + +7. 查询出没有转账交易记录的银行卡账户信息,显示卡号,身份证,姓名,余额。 + +```sql +select CardNo,AccountCode,RealName,CardMoney from AccountInfo a +join BankCard b on a.AccountId=b.AccountId +where CardNo not in (select CardNoOut from CardTransfer) and CardNo not in(select CardNoIn from CardTransfer) +``` \ No newline at end of file diff --git "a/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.20--\346\270\270\346\240\207.md" "b/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.20--\346\270\270\346\240\207.md" new file mode 100644 index 0000000..0e5c517 --- /dev/null +++ "b/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.20--\346\270\270\346\240\207.md" @@ -0,0 +1,260 @@ +# 游标 + +可以将游标看作一种特殊的指针,SQL的游标是一种临时的数据库对象,既可以存放储存在数据库表中数据行的副本,也指向数据行的指针。 + +使用游标,可以实现以下目标 ● 允许定位到结果集中的特定行 ● 从结果集的当前位置检索一行或多行数据 ● 支持对结果集中当前位置的行进行修改 + +## (一)T-SQL游标的分类 + +- **静态游标(Static)** : 在操作游标的时候,数据发生变化,游标中数据不变 +- **动态游标(Dynamic)**: 在操作游标的时候,数据发生变化,游标中数据改变,默认值。 +- **只进游标**:只进游标不支持滚动,只支持从头到尾顺序提取数据,数据库执行增删改,在提取时是可见的,但由于该游标只能进不能向后滚动,所以在行提取后对行做增删改是不可见的。 +- **键集驱动游标(KeySet)**:在操作游标的时候,被标识的列发生改变,游标中数据改变,其他列改变,游标中数据不变。 + +------ + +### 1.游标的生命周期与使用步骤 + +使用游标前4个步骤是必须的 + +- **声明游标** declare:将游标与 T-SQL 语句的结果集相关联,并定义游标的名称、类型和属性,如游标中的记录是否可以更新、删除 + +- ```sql + --1.创建游标(Scroll代表滚动游标,不加Scroll则是只进的,只能支持fetch next) + declare <游标名> cursor scroll for select stuname from stuinfo + ``` + +- **打开游标** open:执行 T-SQL 语句以填充数据。 + +- ```sql + open <游标名> + ``` + +- **读取游标** fetch:从游标的结果集中检索想要查看的行,进行逐步操作。 + +- ```sql + fetch first from <游标名> --结果集的第一行 + fetch last from <游标名> --最后一行 + fetch absolute 1 from <游标名> --从游标的第一行开始数,第n行。 + fetch relative 3 from <游标名> --从当前位置数,第n行。 + fetch next from <游标名> --当前位置的下一行 + fetch prior from <游标名> --当前位置的上一行 + ``` + +- **关闭游标** close:停止游标使用的查询,但并不删除游标的定义,可以使用 OPEN 再次打开。 + +- ```sql + close <游标名> + ``` + +- **释放游标** DEALLOCATE:删除资源并释放其占用的所有资源。 + +**游标的生命周期就包含上面五个阶段** + +------ + +## (二)声明游标cursor + +声明游标是指用 DECLARE 语句创建一个游标。声明游标主要包括以下内容:游标名称、数据来源、选取条件和属性。 + +```sql +declare 游标名称 cursor[local|global]--游标的作用域 +[forward_only|scroll] --游标的移动方向 +[STATIC|KEYSET|DYNAMIC|FAST_FORWARD]--游标的类型 +[READ_ONLY|SCROLL_LOCKS|OPTIMISTIC]--游标的访问类型 +[TYPE_WARNING] --类型转换警告语句 +for select 语句 --select查询语句 +[for{read only|update[of 列名称]}][,...n]--可修改的列 +``` + +参数说明: + +- [Local | Global] :默认为local +- Local:作用域为局部,只在定义它的批处理,存储过程或触发器中有效。 +- Global:作用域为全局,由连接执行的任何存储过程或批处理中,都可以引用该游标。 +- Scroll:代表滚动游标,不加Scroll则是只进的,只能支持fetch next +- forward_only:指定游标智能从第一行滚到最后一行。Fetch Next是唯一支持的提取选项。如果在指定Forward_Only是不指定Static、KeySet、Dynamic关键字,默认为Dynamic游标。如果Forward_Only和Scroll没有指定,Static、KeySet、Dynamic游标默认为Scroll,Fast_Forward默认为Forward_Only +- Static:静态游标 +- KeySet:键集游标 +- Dynamic:动态游标,不支持Absolute提取选项 +- Fast_Forward:指定启用了性能优化的Forward_Only、Read_Only游标。如果指定啦Scroll或For_Update,就不能指定他啦。 +- Read_Only:不能通过游标对数据进行删改。 +- Scroll_Locks:将行读入游标是,锁定这些行,确保删除或更新一定会成功。如果指定啦Fast_Forward或Static,就不能指定他啦。 +- Optimistic:指定如果行自读入游标以来已得到更新,则通过游标进行的定位更新或定位删除不成功。当将行读入游标时,sqlserver不锁定行,它改用timestamp列值的比较结果来确定行读入游标后是否发生了修改,如果表不行timestamp列,它改用校验和值进行确定。如果已修改改行,则尝试进行的定位更新或删除将失败。如果指定啦Fast_Forward,则不能指定他。 +- Type_Warning:指定将游标从所请求的类型隐式转换为另一种类型时向客户端发送警告信息。 +- For Update[of column_name ,....] :定义游标中可==更新==的列。 + +------ + +**示例:** + +```sql +declare student cursor for select * from btb_student +``` + +------ + +## (三)打开游标 + +语法: + +```sql +open 游标名称 |游标变量名称--表示该变量引用了一个游标 +``` + +**在游标被成功打开后,全局 变量 ==@@CORSOR_ROWS== 用来记录游标内的数据行数。返回值有四种:** + +| 返回值 | 描述 | +| ------ | ----------------------------------------------------------- | +| -m | 表示仍在从基础表向游标读入数据,m表示当前在游标中的数据行数 | +| -1 | 该游标是一个动态游标,其返回值无法确定 | +| 0 | 无符合调剂的记录或游标已经关闭 | +| n | 从基础表向游标读入数据已结束,n 为游标中已有的数据记录行数 | + +**示例:打开游标,输出游标中的行数** + +```sql +open curl +select '游标curl数据行数'=@@cursor_rows +``` + +------ + +## (四)读取游标 + +**当游标打开后就可以使用 FETCH 命令从游标中逐行地读取数据,以进行相关处理。** + +语法:fetch[取来] + +```sql +fetch +[[next|prior|first|last|absoute n|relative n]from]--读取数据位置 +[global]游标名称--或者@游标变量名称 [into @游标变量名称][,...n] +``` + +**参数说明:** + +- First:结果集的第一行 +- Prior:当前位置的上一行 +- Next:当前位置的下一行 +- Last:最后一行 +- Absoute n:从游标的第一行开始数,第n行。 +- Relative n:从当前位置数,第n行。 +- Into @variable_name[,...] : 将提取到的数据存放到变量variable_name中。 + +**示例:** + +**提取数据给变量以供它用(取出第3行学生姓名,查询该学生详细信息):** + +```sql +declare @vari varchar(20) +fetch absolute 3 from <游标名> into @vari +select * from StuInfo where stuName = @vari +``` + +**利用游标更新数据**: + +```sql +--更新语法: +-- fetch absolute 3 from <游标名> +-- update 语句 where Current of <游标名> +``` + +------ + +------ + +fetch语句执行时,**==可以使用 全局变量 @@FETCH_STATUS 返回上次执行 fetch 命令的状态。==**在每次用 fetch 从游标中读取数据时,都应检查该变量,以确定上次fetch操作是否成功,来决定如何进行下一步处理。**返回值有三种:** + +| 返回值 | 描述 | +| ------ | ----------------------------------------------- | +| 0 | FETCH命令被成功执行 | +| 1 | FETCH命令失败或者行数据超过游标数据结果集的范围 | +| 2 | 所读取的数据已经不存在 | + +------ + +**示例:创建游标 curl,从游标中提取数据,并查看 FETCH 命令的执行状态。** + +```sql +fetch next from curl +select 'next_fetch执行情况'=@@FETCH_STATUS +``` + +------ + +## (五)关闭游标 + +**游标使用完以后要及时关闭。关闭游标使用 CLOSE ,但不释放游标占用的资源。** + +语法: + +```sql +close [global] 游标名称|游标变量名称 +``` + +------ + +## (六)删除游标 + +**游标关闭后定义还在,需要时可以再使用 OPEN 打开游标继续使用。若确定不再使用则使用 CLOSE 删除游标,释放占用系统中的资源。** + +语法: + +```sql +deallocate [Global] 游标名称|游标变量名称 +``` + +------ + +## (七)完整的步骤演示 + +```sql +--定义一个游标 +declare游标名 cursor scroll for select字段列表 from 表名 +--打开游标 +open 游标名 +--定义变量,用于存放游标读取出来的值 +declare @xxx 数据类型 +--读取游标的第一条数据,并存放在变量中 +fetch first from 游标名 into @xxx +--循环记录游标读取的数据 +print '读取的数据如下:' +while(@@FETCH_STATUS =0) + begin + --使用print输出读取的数据 + print'文字说明:'+xxx + --读取下一条记录 + fetch next from 游标名 into @xxx + end +--读取完成后关闭游标 +close 游标名 +go +--删除游标 +deallocate 游标名 +go +``` + +例题:**创建游标指向某行多列数据,并循环显示数据:** + +```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 <游标名> +``` \ No newline at end of file diff --git "a/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.21--\350\207\252\345\256\232\344\271\211\345\207\275\346\225\260.md" "b/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.21--\350\207\252\345\256\232\344\271\211\345\207\275\346\225\260.md" new file mode 100644 index 0000000..3abd8f5 --- /dev/null +++ "b/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.21--\350\207\252\345\256\232\344\271\211\345\207\275\346\225\260.md" @@ -0,0 +1,195 @@ +# 自定义函数 + +**在SQL server中不仅可以可以使用系统自带的函数(时间函数、聚合函数、字符串函数等等),还可以根据需要自定义函数。** + +**用户自定义函数的类型:** + +1. 标量值函数(返回一个标量值) +2. 表格值函数(内联表格值函数、多语句表值函数,返回一个结果集即返回多个值) + +**三种定义函数的不同点与共同点:** + +1. 标量值函数返回的是一个数据类型值 + + 内联表值函数返回的是一个table + + 多语句表值函数返回的是一个table的变量(类似前面两个的结合) + +2. 语法的结构:标量值函数和多语句表值函数都是要有begin.........................end,内联表值函数就没有 + +3. 调用:标量函数要写成在dbo.function_name; + +**共同点:他们的创建定义相同** + +```sql +create function 函数名(传入参数的名称 传入参数的类型) +returns 返回值数据类型 +as +``` + +**函数参数** + +参数可以是常量、表中的某个列、表达式或其他类型的值。在函数中有三种类型的参数。 + +1. 输入:指必须输入一个值。 +2. 可选值:在执行该参数时,可以选择不输入参数。 +3. 默认值:函数中默认有值存在,调用时可以不指定该值。 + +------ + +## (一)标量值函数的定义 + +```sql +create function 函数名称(参数名 参数的数据类型) +returns 返回返回值的数据类型 +[with encryption]--如果指定了encryption则函数被加密 +[as] +begin +--函数体(即 t-sql语句) +return 表达式 +end +``` + +示例:通过学生名字输出成绩 + +```sql +create function dbo.student_name_score(@sname nvarchar(30)) +returns int +as +begin + declare @sscore int + select @sscore=score from student where name=@sname + return @sscore +end + +select dbo.student_name_score('张三') name;--调用一定要在名称前加上dbo.,定义的时候如果名称前面没有dbo.调用也要加上 +``` + +------ + +## (二)内联表格值函数 + +**语法:** + +特点:内联表格值函数支持在where子句中使用参数 + +```sql +create function 函数名称(参数名 参数的数据类型) +returns table--返回一个表 +[with encryption]--如果指定了encryption则函数被加密 +[as] +--函数体(即 t-sql语句) +return (一条sql语句) +``` + +**示例:**通过id差姓名和成绩 + +```sql +create function dbo.student_name_score2(@sid int) +returns table +as +return select name,score from student where id=@sid + +select * from dbo.student_name_score2(3) +``` + +------ + +## (三)多语句表值函数 + +多语句表值函数跟内联表值函数都是表值函数,它们返回的结果都是Table类型。多语句表值函数通过多条语句来创建Table类型的数据。**这里不同于内联表值函数,内联表值函数的返回结果是由函数体内的SELECT语句来决定。而多语句表值函数,则是需要指定具体的Table类型的结构。**也就是说返回的Table已经定义好要哪些字段返回。所以它能够支持多条语句的执行来创建Table数据。 + +**语法:** + +```sql +create function 函数名称(@参数名 参数的数据类型) +returns @Table_Variable_Name table (Column_1 culumn_type,Column_2 culumn_type) +--returns @表变量 table 表的定义(即列的定义和约束) +[with encryption] --如果指定了encryption则函数被加密 +[as] +begin + 函数体(即T-SQL 语句) +return +END +``` + +**示例:**通过id查询该学生所有信息的函数 + +```sql +create function dbo.student_table_id(@sid int) +returns @table_test table(id int ,name nvarchar(30),score int) +as +begin +insert @table_test select id,name,score from student where id=@sid +--把student表查询结果插入@tabel——test +return +end + +select * from dbo.student_table_id(1) +``` + +------ + +## (四)自定义函数的修改和删除 + +### 1.使用alter语句修改自定义函数: + +```sql +alter function 函数名(参数) +returns table +as +return(一条SQL语句) +``` + +### 2.使用drop语句删除: + +```sql +drop function func_date_get_name +``` + +------ + +(五)编写函数的注意事项 + +**标量函数:** + +1. ```sql + 所有的入参前都必须加@ + ``` + +2. ```sql + create后的返回,单词是returns,而不是return + ``` + +3. ```sql + returns后面的跟的不是变量,而是返回值的类型,如:int,char等。 + ``` + +4. ```sql + 在begin/end语句块中,是return。 + ``` + +**内联表格值函数:** + +1. ```sql + 只能返回table,所以returns后面一定是TABLE + ``` + +2. ```sql + AS后没有begin/end,只有一个return语句来返回特定的记录。 + ``` + +**多语句表值函数:** + +1. ```sql + returns后面直接定义返回的表类型,首先是定义表名,表明前面要加@,然后sql是关键字TABLE,最后是表的结构。 + ``` + +2. ```sql + 在begin/end语句块中,直接将需要返回的结果insert到returns定义的表中就可以了,在最后return时,会将结果返回。 + ``` + +3. ```sql + 最后只需要return,return后面不跟任何变量。 + ``` + diff --git "a/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.22--\346\255\273\351\224\201.md" "b/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.22--\346\255\273\351\224\201.md" new file mode 100644 index 0000000..1de75ee --- /dev/null +++ "b/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.22--\346\255\273\351\224\201.md" @@ -0,0 +1,82 @@ +# 死锁 + +## 关联子查询 + +#### 同表关联一个一个对照查询 + +```sql +--子查询 +select * from tb_student +where birth in (select min(birth) from tb_student group by gender) + +--关联子查询 +select * from tb_student t1 where birth =(select min(birth) from tb_student t2 + where t2.gender=t1.gender) + --=返回标量 + +--先在t1(外层查询)查询数据: gender已经查询出来了 +--在内部一行一行查询 + + +--部门工资最高的员工:部门名称,员工名称,薪水 +select * from Department d join Employee e on d.id=e.departmentId +where salary in (select max(salary) from Employee group by departmentId) + +--关联子查询 +select * from Department d join Employee e on d.id=e.departmentId +where salary = +(select max(salary) from +Employee e1 where e.departmentId=e1.departmentId) + +同表关联一个一个对照查询 +``` + +## 排序 + +```sql +over +frame: rows between unbounded preceding and current row +unbounded preceding:第一行 +current row:当前行 +select score,max(score) +over (order by stuid asc rows between current row and 1 following) frame +from stuscore + +frame:rows, range +between ... and ... +unbounded preceding: 第一行 +unbounded following: 最后一行 +CURRENT ROW: 当前行 +ROWS:逻辑位置存储 RANGE:物理位置存储 + 行号 preceding: 前面几行 + 行号 following: 后面几行 +``` + +## 死锁(事务) + +#### 死锁产生的原因 + +A事务和B事务需要使用资源1,2,但是A事务占用了资源1,B事务占用了资源2,两个事务同时等待对方资源释放。 死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占用不会释放的资源而处于的一种永久等待状态。 + +#### 防止死锁产生: + +语句保持一致 事务语句不要写太长 + +```sql +--A用户 +--begin transaction: A-->语句1 +--语句1 update StuInfo set classid = 2 where StuName='黄炜杰' +--语句2 update StuInfo set classid = 2 where StuName='李雅芸' +--commit transaction + + +--B用户 +--begin transaction: B-->语句1 +--语句1: update StuInfo set classid = 2 where StuName='李雅芸' +--语句2: update StuInfo set classid = 2 where StuName='黄炜杰' +--commit transaction +``` + +事务只能整体完成 + +当一个事务无法结束时,另一个与之有关的事务就会陷入死锁,占用资源永久等待 \ No newline at end of file diff --git "a/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.26--\345\255\230\345\202\250\350\277\207\347\250\213.md" "b/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.26--\345\255\230\345\202\250\350\277\207\347\250\213.md" new file mode 100644 index 0000000..4a5c95e --- /dev/null +++ "b/38\345\274\240\351\235\231/\347\254\224\350\256\260/9.26--\345\255\230\345\202\250\350\277\207\347\250\213.md" @@ -0,0 +1,145 @@ +# 存储过程 + +### 概念 + +​ 1.存储过程,也叫做存储程序,是一条或者多条SQL语句的集合,可以视为批量处理,但是其作用不仅仅局限于批量处理。 + +​ 2.其中针对存储过程也有多种操作:如何创建存储过程,以及如何调用、查看、修改、删除存储过程。存储 过程也可以调用其他存储过程。 + +#### 常见的系统存储过程有 + +==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 +``` + +例如:查询年龄最小的学生(引用students表信息) + +```sql +create proc proc_GetMaxBirth +as +select max(birth) 最小出生日期 from tb_student +go +``` + +2.带参数,无返回的情况 + +```sql +create proc <存储过程名称> +<变量1> <数据类型> +<变量2> <数据类型> +... +as + +go +``` + +```sql +例如: +create proc proc_GetBookInfoByCategory +@cg varchar(30) +as +select name,publishing from tb_bibliography where category=@cg + +go +``` + +3.有输入参数,没有输出参数,但是有返回值的存储过程(返回值必须整数) + +(1.直接在存储过程里写查询语句,执行的时候会在结果显示 + +2.return语句,只能返回int型数据) + +```sql +create proc <存储过程名称> +<变量1> <数据类型> +<变量2> <数据类型> +... +as + +return 整数 +go +``` + +例如:输入学号,查询该生是否还能借书(最多能借2本书),返回还能借几本 (0) + +```sql +create proc proc_GetRestBoo +@stunum varchar(30) +as + declare @rest varchar(2) + set @rest = 2 - (select count(*) 已借书 from tb_record where stu_num=@stunum) + return --返回的是整型数据 +go +``` + +4.有输入参数,有输出参数的存储过程 & 一个变量具备同时输入输出参数的存储过程 + +```sql +create proc <存储过程名称> +<变量1> <数据类型> output +<变量2> <数据类型> output +... +as + +return 整数 +go +``` + +out 参数 执行存储过程之前 没有赋值, 执行完后将值带出来 + +```sql +例如: +create proc proc_GetRestBookss +@stunum varchar(300), +@rest varchar(2) output +as + set @rest = 2 - (select count(*) 已借书 from tb_record where stu_num=@stunum) +go +``` + + in参数 : 有进无出(输出的仍然是执行之前的值) + +```sql +例如: +create proc proc_GetRestBooksss +@stunum varchar(300), +@rest varchar(2) +as + set @rest = 2 - (select count(*) 已借书 from tb_record where stu_num=@stunum) +go +``` + +**删除存储过程** + +```sql +drop procedure <存储过程名称> +``` + +例如:删除“周泽强同学的信息” + +```sql +drop procedure proc_Zhouzeqiang +``` + -- Gitee