From 1dfc011f9ed60dae4d1a3a9a3a652ec3ebd4e922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?33=E8=B0=B7=E5=85=86=E6=98=8E?= <2692544974@qq.com> Date: Wed, 7 Sep 2022 20:46:42 +0800 Subject: [PATCH] 1 --- ...07\346\227\245\344\275\234\344\270\232.md" | 52 ++ ...33\351\230\266\347\254\224\350\256\260.md" | 551 ++++++++++++++++++ 2 files changed, 603 insertions(+) create mode 100644 "33\350\260\267\345\205\206\346\230\216/9\346\234\2107\346\227\245\345\206\205\345\256\271/9\346\234\2107\346\227\245\344\275\234\344\270\232.md" create mode 100644 "33\350\260\267\345\205\206\346\230\216/9\346\234\2107\346\227\245\345\206\205\345\256\271/sql\350\277\233\351\230\266\347\254\224\350\256\260.md" diff --git "a/33\350\260\267\345\205\206\346\230\216/9\346\234\2107\346\227\245\345\206\205\345\256\271/9\346\234\2107\346\227\245\344\275\234\344\270\232.md" "b/33\350\260\267\345\205\206\346\230\216/9\346\234\2107\346\227\245\345\206\205\345\256\271/9\346\234\2107\346\227\245\344\275\234\344\270\232.md" new file mode 100644 index 0000000..ec6e0e8 --- /dev/null +++ "b/33\350\260\267\345\205\206\346\230\216/9\346\234\2107\346\227\245\345\206\205\345\256\271/9\346\234\2107\346\227\245\344\275\234\344\270\232.md" @@ -0,0 +1,52 @@ +```sql +--1.关羽的银行卡号为"6225547858741263",查询出余额比关羽多的银行卡信息,显示卡号,身份证,姓名,余额。 +select b.CardNo'卡号',a.AccountCode'身份证',a.RealName'姓名',b.CardMoney'余额' from BankCard as b +join AccountInfo as a on b.AccountId = a.AccountId +where CardMoney >(select CardMoney from BankCard where CardNo =6225547858741263) + +--2.从所有账户信息中查询出余额最高的交易明细(存钱取钱信息)。 +declare @inmoney money +declare @outmoney money +select @inmoney=max(MoneyInBank),@outmoney=max(MoneyOutBank) from CardExchange +if @inmoney>0 + begin + print '存入'+cast(@inmoney as char)+'元' + end + if @outmoney>0 + begin + print '取出'+@outmoney+'元' + end +else + print '没有交易记录' + +--3.查询有取款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额 +select s1.CardNo,s3.AccountCode,s3.RealName,s2.CardMoney from CardExchange as s1 +join BankCard as s2 on s1.CardNo=s2.CardNo +join AccountInfo as s3 on s2.AccountId = s3.AccountId +where MoneyOutBank !=0.00 + +--4.查询出没有存款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额。 +select b.CardNo'卡号',a.AccountCode'身份证',a.RealName'姓名',b.CardMoney'余额' from AccountInfo as a join BankCard as b on a.AccountId=b.AccountId +where a.AccountId in (select AccountId from BankCard where CardMoney =0.00) +--5.关羽的银行卡号为"6225547858741263",查询当天是否有收到转账。 +declare @Transfermoney money +select @Transfermoney=TransferMoney from CardTransfer where CardNoIn=6225547858741263 +if @Transfermoney>0 + begin + print'收到转账' + end +else + print'没收到转账' + +--6.查询出交易次数(存款取款操作)最多的银行卡账户信息,显示:卡号,身份证,姓名,余额,交易数。 +select s2.CardMoney,s2.CardNo,s1.CardNo,count(s1.CardNo)'交易数' from CardExchange as s1 +left join BankCard as s2 on s1.CardNo = s2.CardNo +group by s1.CardNo + +--7.查询出没有转账交易记录的银行卡账户信息,显示卡号,身份证,姓名,余额。 +select s2.CardNo'卡号',s3.AccountCode'身份证',s3.RealName'姓名',s2.CardMoney'余额' from CardTransfer as s1 +right join BankCard as s2 on s1.CardNoOut=s2.CardNo +right join AccountInfo as s3 on s2.AccountId = s3.AccountId +where s1.CardNoOut is null +``` + diff --git "a/33\350\260\267\345\205\206\346\230\216/9\346\234\2107\346\227\245\345\206\205\345\256\271/sql\350\277\233\351\230\266\347\254\224\350\256\260.md" "b/33\350\260\267\345\205\206\346\230\216/9\346\234\2107\346\227\245\345\206\205\345\256\271/sql\350\277\233\351\230\266\347\254\224\350\256\260.md" new file mode 100644 index 0000000..d49a08e --- /dev/null +++ "b/33\350\260\267\345\205\206\346\230\216/9\346\234\2107\346\227\245\345\206\205\345\256\271/sql\350\277\233\351\230\266\347\254\224\350\256\260.md" @@ -0,0 +1,551 @@ + + + + + + +# sql server进阶 + +[TOC] + + + +# 数据库设计相关理论 + +## 一、数据库设计是什么?它重要吗? + +1. 根据业务需求的描述,设置或者配置数据库的各项参数,包括数据库、数据库表、数据库表的字段、主键、外键、约束、索引、存储过程、函数、视图等等一系列东西的过程 +2. 重要不?很重要,或者说非常的重要,因为,现代的绝大多数的应用需要数据库的支撑 + +## 如何进行数据库的设计 + +1. 根据业务的需求设计数据库,有一套规范叫 三范式 +2. 还有一种设计工具PowerDesigner + +![img](https://gitee.com/gu-zhaoming/database-advanced-class-notes-1/raw/master/%E8%80%81%E8%83%A1%E6%9D%A5%E4%B9%9F/imgs/db.png) + + + + + +## 数据持久化 + +``` +## 数据易失,希望保存数据,则关系到一个数据持久化的概念 + +## 数据持久化的方式 保存到文件、保存到数据库(实际上也保存到数据库文件当中) + +## 数据放在硬盘上,放在文件当中,那么你总需要这个数据按一定的逻辑或者层次进行摆放 +``` + +## + +# sql server三范式理解 + +### 第一范式: + +```sql +--指数据表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的 某个属性不能有多个值或者不能有重 复的属性。 +``` + +### 第二范式: + +```sql +--如果一个数据表已经满足第一范式,而且该数据表中的任何一个非主键字段的数值都 依赖于该数据表的主键字段,那么该 数据表满足第二范式。 这个表中,就是这个选出来的字段中,非主键字段要完全依赖主键字段 +``` + +### 第三范式: + +```sql +--如果一个数据表已经满足第二范式,而且该数据表中的任何两个非主键字段的数值之 间不存在函数依赖关系,那么该数据 表满足第三范式。 这个表中,就是这个选出来的字段中,不能有函数依赖关系 +``` + +### BC范式 + +```sql +--在关系模式中每一个决定因素都包含候选键,也就是说,只要属性或属性组A能 够决定任何一个属性B,则A的子集中必须 有候选键。BCNF范式排除了任何属性(不光 是非主属性,2NF和3NF所限制的都是非主属性)对候选键的传递依赖与部分 依赖。 +``` + +# 变量 + +## 局部变量 + +局部变量必须以标记@作为前缀 ,如@age +局部变量的使用是先声明,再赋值 +局部变量只在定义它的局部范围内有效 + + + +声明一个局部变量:**declare @变量名 数据类型** + +```sql +--例: + declare @id int --声明一个名为id的整型变量 + declare @name varchar(50) --声明一个可变长度为50的存放姓名的字符串变量 + +``` + +赋值: + +- set @变量名 = 值 + +- select @变量名 = 值 + +```sql +--例: + select @id = 1001 + set @name = '周飘' +``` + +set与select赋值的区别: + +set赋值给变量指定的值,select一般用于表中查询出的数据赋值给变量,如果查询结果有多条,取最后一条赋值给变量 + +## 全局变量 + +全局变量必须以标记@@作为前缀,如@@version +全局变量由**系统定义和维护**,我们**只能读取,不能修改全局变量的值** +全局变量在整个SQL环境下都可以被访问或调用 + +```sql +--@@ERROR:返回执行的上一个语句的错误号 +--@@IDENTITY:返回最后插入的标识值 +--@@MAX_CONNECTIONS:返回允许同时进行的最大用户连接数 +--@@ROWCOUNT:返回受上一语句影响的行数 +--@@SERVERNAME:返回运行 SQL Server 的本地服务器的名称 +--@@SERVICENAME:返回 SQL Server 正在其下运行的注册表项的名称 +--@@TRANCOUNT:返回当前连接的活动事务数 +--@@LOCK_TIMEOUT:返回当前会话的当前锁定超时设置(毫秒) +``` + +## 输出语句 + +1. print变量或表达式 +2. select变量或表达式 + +```sql +--例: + print '数据库服务器名:' + @@servicename + select 15*8 +``` + + + +#### 使用convert函数 + +​ 由于PRINT 命令向客户端返回一个结果的字符串的信息。如果变量值不是字符串的话必须先用数据类型转换函数 CONVERT 将其转换为字符串。 + +```sql +--显示自动编号 +print '当前自动编号的值:' + convert(varchar(10),@@IDENTITY) +``` + +## 逻辑控制语句 + +### if...else... + +语句: + +```sql +IF(条件表达式) + BEGIN --相当于C#里的{ + 语句1 + …… + END --相当于C#里的} +ELSE + BEGIN + 语句1 + …… + END +``` + +例子: + +```sql +--1.查询S2002总分有没有超过250: 如果没有超过, 打印 不合格 超过250 打印合格 +declare @tscore int + +select @tscore = Chinese+English+Math from StuScore where StuID='S2001' + +print @tscore + +if @tscore>=240 +begin + if @tscore >=245 + begin + print '优秀' + end + else + begin + print '合格' + end +end +else +begin + print '不合格' +end +``` + +```sql +--2.判断男生平均成绩是否高于女生,如果男生平均成绩比女生高,输出男生中的第一名, 否则输出女生中的第一名 +--查出男生,女生的平均成绩 +declare @maleScore float--男生平均成绩 +declare @femaleScore float--女生 +declare @max int --最高分 + +select @maleScore = avg(chinese+english+math) from StuScore where StuSex='男' --男生平均成绩 +select @femaleScore = avg(chinese+english+math) from StuScore where StuSex='女' --女生 + +if @maleScore>@femaleScore +begin + print '男生平均成绩高' + --男生第一名 + --max + --select @max = max(chinese+english+math) from StuScore where StuSex='男' + --print '男生最高分'+@max + select top 1 * from StuScore where Stusex = '男' order by (English+Chinese+Math) desc +end +else +begin + print '女生平均成绩高' + --select @max = max(chinese+english+math) from StuScore where StuSex='女' + --print '女生最高分'+@max + + select top 1 * from StuScore where StuSex='女' order by (English+Chinese+Math) desc +end +``` + +```sql +--3.计算平均分数并输出,如果平均分数超过分输出成绩最高的三个学生的成绩,否则输出后三名的学生 +declare @avg int --定义变量 +select @avg= AVG(english) from Score --为变量赋值 +select '平均成绩'+CONVERT(varchar,@avg) --打印变量的值 + if @avg<60 + begin + select '前三名' + select top 3 * from Score order by english desc + end + else + begin + select '后三名' + select top 3 * from Score order by english + end +``` + +```sql +--4. 为赵云此人进行开户开卡操作,赵云身份证:420107199904054233 +declare @AccountId varchar +if exists(select * from AccountInfo where AccountCode=420107199904054233) + begin + select @AccountId =(select AccountId from AccountInfo WHERE AccountCode='420107199904054233') + insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState) + values('6225547858741233',2,'123456',0,1) + end +else + begin + insert into AccountInfo(AccountCode,AccountPhone,RealName,OpenTime) + values('420107199904054233','17634449035','赵云',GETDATE()) + set @AccountId=@@IDENTITY + insert into BankCard(CardNo,AccountId,CardPwd,CardMoney,CardState) + values('6225547858741666',@AccountId,'123456',0,1) + end +``` + + + +### case-when + +例子: + +```sql +1、case…end (具体的值) +case后面有值,相当于c#中的switch case +注意:case后必须有条件,并且when后面必须是值不能为条件。 +-----------------case--end---语法结构--------------------- +select name , --注意逗号 + case level --case后跟条件 + when 1 then '骨灰' + when 2 then '大虾' + when 3 then'菜鸟' + end as'头衔' +from [user] +``` + +```sql +2、case…end (范围) +case 后面无值,相当于c#中的if…else if…else…. +注意:case后不根条件 +------------------case---end-------------------------------- +select studentId, + case + when english between 80 and 90 then '优' + when english between 60 and 79 then '良' + else '差' + end + from Score +------------------case---end-------------------------------- +select studentId, + case + when english >=80 then '优' + when english >=60 then '良' + else '差' + end + from Score +----------------------------------------------------- +select *, + case + when english>=60 and math >=60 then '及格' + else '不及格' + end +from Score +``` + +```sql +--3.将成绩表中的学生成绩用五分制显示 +select stuName,stuID,english, +case + when english>=80 then '5分' + when english>=60 then '4分' + when english>=40 then '3分' + when english>=20 then '2分' + when english>=0 then '1分' + else '0分' +end '5分制' +from StuScore +inner join StuInfo on StuScore.StuID = StuInfo.StuNo +``` + +```sql +--4.查询银行卡信息,将银行卡状态1,2,3,4分别转换为汉字“正常,挂失,冻结,注销”, +--并且根据银行卡余额显示银行卡等级 30万以下为“普通用户”,30万及以上为"VIP用户", +--显示列分别为卡号,身份证,姓名,余额,用户等级,银行卡状态。 +select CardNo,AccountCode,RealName,CardMoney, +case + when cardmoney>300000 then 'VIP用户' + when cardmoney<300000 then '普通用户' +end '用户等级', + +case + when CardState =1 then '正常' + when CardState =2 then '挂失' + when CardState =3 then '冻结' + when CardState =4 then '注销' +end '银行卡状态' +from BankCard +join AccountInfo on AccountInfo.AccountId=BankCard.AccountId +``` + +```sql +--5.某用户银行卡号为“6225547854125656”,该用户执行取钱操作,取钱5000元, +--余额充足则进行取钱操作,并提示"取钱成功",否则提示“余额不足”。 +declare @mon money,@carno varchar(20)='6225547854125656' +select @mon=CardMoney from BankCard where CarNo = 6225547854125656 +print @mon +if @mon>5000 +begin + update BankCard set CardMoney = CardMoney-5000 where CardNo=@carno + insert into CardExchange values(@carno,0,5000,GETDATE()) + print '取钱成功' +end +else +begin + print '余额不足' +end +``` + + + +### while + +可以通过break和continue控制循环语句中的执行。 + +语句: + +```sql +WHILE(条件表达式) + BEGIN --相当于C#里的{ + 语句 + …… + BREAK + END --相当于C#里的} +``` + +例子: + +```sql +--1.循环打印1到10 +declare @a int = 1 +while (@a <= 10) +begin + print @a + set @a = @a + 1 +end +``` + +```sql +--2.打印99乘法表 +declare @i int = 1 + +while @i<=9 +begin + declare @j int = 1 + declare @result varchar(500) = '' + while @j<=@i + begin + --显示 + --不会自动转换类型,需要强转 + --set @result = @result + convert(varchar(2), @i) + ' * ' + convert(varchar(2), @j) + ' = '+ convert(varchar(2),@i*@j) + char(9) + --cast + set @result = @result + cast(@i as varchar(1)) + ' * ' + cast(@j as varchar(1)) + ' = '+ cast(@i*@j as varchar(1)) + char(9) + --控制J变量 + set @j =@j + 1 + end + print @result + set @i = @i + 1 +end +``` + +```sql +--3.如果不及格的人超过半数(考试题出难了),则给每个人增加分 +select * from Score +declare @conut int,@failcount int,@i int=0 --定义变量 +select @conut =COUNT(*) from Score --统计总人数 +select @failcount =COUNT(*) from Score where english<100 --统计未及格的人数 +while (@failcount>@conut/2) + begin + update Score set english=english+1 + select @failcount=COUNT(*) from Score where english<100 + set @i=@i+1 + end +select @i +update Score set english=100 where english >100 +``` + +### 连接 + +例子: + +```sql +select sName,sAge, + case + when english <60 then '不及格' + when english IS null then '缺考' + else CONVERT(nvarchar, english) + end as'英语成绩' +from student as s +left join Score as c on s.sid =c.sid + +内连接 inner join...on... + 查询满足on后面条件的数据 + + 外连接 + 左连接 + left join...on... + 先查出左表中的所有数据 + 再使用on后面的条件对数据过滤 + 右连接 + right join...on... + 先查出右表中的所有数据 + 再使用on后面的条件对数据过滤 + 全连接 + full join ...on... + +(*)交叉连接 + cross join 没有on + 第一个表的每一行和后面表的每一行进行连接 + 没有条件。是其它连接的基础 +``` + +```sql +--练习:将StuScore成绩表中的学生成绩用五分制显示。 +--​ 5分:80分以上 +--​ 4分:60~79分 +--​ 3分:40~59分 +--​ 2分:20~39分 +--​ 1分:0~19分 +select stuName,stuID,english, +case + when english>=80 then '5分' + when english>=60 then '4分' + when english>=40 then '3分' + when english>=20 then '2分' + when english>=0 then '1分' + else '0分' +end '5分制' +from StuScore +inner join StuInfo on StuScore.StuID = StuInfo.StuNo +``` + +## 批处理语句 + +go语句特点: + +1. 等待go语句前的代码执行完成后,再执行go后面的代码。 +2. 批处理语句的结束标志。 + +```sql +--下面的@num变量作用域为全局 +--declare @num int +--set @num = 0 + +--下面的@num变量的作用域是局部,只在两个go之间可以使用,最后一行代码会报错 +--.........sql代码 +--go +--declare @num int +--set @num = 0 +--go +--set @num = 1 +``` + +### 比较运算符 + +SQLServer中有三个关键字可以修改比较[运算符](https://so.csdn.net/so/search?q=运算符&spm=1001.2101.3001.7020):All、Any和Some,其中Some和Any等价 + +```sql +set nocount on + +use tempdb +go + +if (object_id ('t1') is not null)drop table t1 +create table t1 (n int) +insert into t1 select 2 unionselect 3 + +if (object_id ('t2') is not null)drop table t2 +create table t2 (n int) +insert into t2 select 1 unionselect 2 union select 3 union select 4 + +-- t1表数据 2,3 +-- t2表数据 1,2,3,4 +-- '>all' 表示:t2表中列n的数据大于t1表中列n的数据的数,结果只有4. +select * from t2 where n > all(select n from t1 ) --4 +select * from t2 where n > any(select n from t1 ) --3,4 +select * from t2 where n > some(selectn from t1) --3,4 + +select * from t2 where n = all(select n from t1 ) --无数据 +select * from t2 where n = any(select n from t1 ) --2,3 +select * from t2 where n = some(selectn from t1) --2,3 + +select * from t2 where n < all(select n from t1 ) --1 +select * from t2 where n < any(select n from t1 ) --1,2 +select * from t2 where n < some(selectn from t1) --1,2 + +select * from t2 where n <>all (select n from t1 ) --1,4 +select * from t2 where n <>any (select n from t1 ) --1,2,3,4 +select * from t2 where n <>some(select n from t1) --1,2,3,4 +set nocount off +``` + +注意: + +1. =any 与in 等效. + +2. 如果t1中包含null数据,那么所有All相关的比较运算将不会返回任何结果。因为t1和t2表的null的存在他们和notexists之类的比较符会有一些区别。 + 比如下面两句 + +```sql +select * from t2 a where not exists(select1 from t1 where n>=a.n) + +select * from t2 where n > all(select n from t1) +``` + -- Gitee