diff --git "a/46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/2022.9.6--\346\237\245\350\257\242\344\275\234\344\270\232.md" "b/46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/2022.9.6--\346\237\245\350\257\242\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..06748a0d235f8b7949664c2a39d18132d5373bac --- /dev/null +++ "b/46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/2022.9.6--\346\237\245\350\257\242\344\275\234\344\270\232.md" @@ -0,0 +1,95 @@ +```sql +--1. 为赵云此人进行开户开卡操作,赵云身份证:420107199904054233 +declare @zy varchar(20), @zyp varchar(20),@zyN varchar(20),@zyT smalldatetime +set @zy='420107199904054233' +set @zyp='12345678978' +set @zyN='赵云' +set @zyT=GETDATE() +insert AccountInfo values(@zy,@zyp,@zyN,@zyT) + +declare @zyc varchar(30),@zyi int, @zym varchar(30),@zyq money ,@zyz int, @zyti smalldatetime +set @zyc='6225547854165656' +set @zyi='4' +set @zym='123456' +set @zyq='500000' +set @zyz='1' +set @zyti=GETDATE() +insert BankCard values(@zyc,@zyi,@zym,@zyq,@zyz,@zyti) + + + +--2. 需要求出张飞的银行卡卡号和余额,张飞身份证:420107199602034138 (1.使用连接查询,2.使用变量) +declare @ZF varchar(20),@Carmoney money +select @ZF= CardNo from AccountInfo inner join BankCard on AccountInfo.AccountId=BankCard.AccountId where BankCard.AccountId='3' +select @Carmoney= CardMoney from AccountInfo inner join BankCard on AccountInfo.AccountId=BankCard.AccountId where BankCard.AccountId='3' +print @ZF +print @Carmoney +--#### 逻辑控制 + +-- 条件分支if-else + + + +--​ 3.某用户银行卡号为“6225547854125656”,该用户执行取钱操作,取钱5000元,余额充足则进行取钱操作,并提示"取钱成功",否则提示“余额不足”。 +declare @Money money +select @Money=CardMoney from BankCard where CardNo='6225547854125656' +print @Money +if @Money>=5000 +begin + set @Money=@Money-5000 + print'取钱成功' + print @Money +end +else print'余额不足' +-- 条件分支:case-when + + + + +--​ 4.查询银行卡信息,将银行卡状态1,2,3,4分别转换为汉字“正常,挂失,冻结,注销”,并且根据银行卡余额显示银行卡等级 30万以下为“普通用户”,30万及以上为"VIP用户", +----显示列分别为卡号,身份证,姓名,余额,用户等级,银行卡状态。 + +select CardNo 卡号,AccountCode 身份证,RealName 姓名,CardMoney 余额, +case +when CardMoney>=300000 then 'VIP用户' +when CardMoney>=0 then '普通用户' +else '无' +end '用户等级', +case +when CardState='1' then '正常' +when CardState='2' then '挂失' +when CardState='3' then '冻结' +when CardState='4' then '注销' +end '银行卡状态' +from BankCard inner join AccountInfo on BankCard.AccountId=AccountInfo.AccountId +--**while** + + + +--​ 5.循环打印1-10。 +declare @a int=1 +while (@a<10) +begin + set @a=@a+1 + print @a +end + + +--6、99乘法表 +declare @i int = 1 + +while @i<=9 +begin + declare @j int = 1 + declare @result varchar(500) = '' + while @j<=@i + begin + + set @result = @result + cast(@i as varchar(1)) + ' * ' + cast(@j as varchar(1)) + ' = '+ cast(@i*@j as varchar(1)) + char(9) + set @j =@j + 1 + end + print @result + set @i = @i + 1 +end +``` + diff --git "a/46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/2022.9.7--\345\255\220\346\237\245\350\257\242\344\275\234\344\270\232.md" "b/46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/2022.9.7--\345\255\220\346\237\245\350\257\242\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..9c655e04fdd8c615d54638e736ac3a7f53ea261d --- /dev/null +++ "b/46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/2022.9.7--\345\255\220\346\237\245\350\257\242\344\275\234\344\270\232.md" @@ -0,0 +1,37 @@ +```sql +--1. 关羽的银行卡号为"6225547858741263",查询出余额比关羽多的银行卡信息,显示卡号,身份证,姓名,余额。 +select bc.CardNo,ac.AccountCode,ac.RealName,bc.CardMoney from AccountInfo ac +inner join BankCard bc on ac.AccountId = bc.AccountId +where bc.CardMoney > all(select bc.CardMoney from AccountInfo ac + inner join BankCard bc on ac.AccountId = bc.AccountId + where ac.RealName = '关羽') + +--2. 从所有账户信息中查询出余额最高的交易明细(存钱取钱信息)。 +select bc.CardNo, ce.MoneyInBank 存钱 , ce.MoneyOutBank 取钱 from CardExchange ce +inner join BankCard bc on ce.CardNo = bc.CardNo +where bc.CardMoney = (select max(BankCard.CardMoney) from BankCard) + +--3. 查询有取款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额。 +select b.* from CardStateChange c +inner join BankCard b on b.CardNo=c.CardNo +where c.CardNo =some (select CardNo from CardExchange where MoneyOutBank !=0 ) +--4. 查询出没有存款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额。 +select b.* from CardStateChange c +inner join BankCard b on b.CardNo=c.CardNo +where c.CardNo =some (select CardNo from CardExchange where MoneyInBank =0 ) +--5. 关羽的银行卡号为"6225547858741263",查询当天是否有收到转账。 + +if exists(select * from CardTransfer where CardNoIn = '6225547858741263' +and convert(varchar(10),TransferTime, 120) = convert(varchar(10),getdate(), 120) +) + print '有转账记录' +else + print '没有转账记录' +--6. 查询出交易次数(存款取款操作)最多的银行卡账户信息,显示:卡号,身份证,姓名,余额,交易数。 + +select b.CardNo 卡号 ,AccountCode 身份证,RealName 姓名,CardMoney 余额,交易次数 from AccountInfo a +inner join BankCard b on a.AccountId=b.AccountId +inner join (select CardNo, count(*) 交易次数 from CardExchange group by CardNo) T on b.CardNo=T.CardNo +where 交易次数 =(select max(交易次数) from (select CardNo,count(*) 交易次数 from CardExchange group by CardNo) T) +``` + diff --git "a/46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/Snipaste_2022-09-04_20-17-39.png" "b/46\350\265\226\346\235\260\346\236\227/\345\233\276\347\211\207/Snipaste_2022-09-04_20-17-39.png" similarity index 100% rename from "46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/Snipaste_2022-09-04_20-17-39.png" rename to "46\350\265\226\346\235\260\346\236\227/\345\233\276\347\211\207/Snipaste_2022-09-04_20-17-39.png" diff --git "a/46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/\351\223\266\350\241\214\345\215\241\344\277\241\346\201\257.png" "b/46\350\265\226\346\235\260\346\236\227/\345\233\276\347\211\207/\351\223\266\350\241\214\345\215\241\344\277\241\346\201\257.png" similarity index 100% rename from "46\350\265\226\346\235\260\346\236\227/\344\275\234\344\270\232/\351\223\266\350\241\214\345\215\241\344\277\241\346\201\257.png" rename to "46\350\265\226\346\235\260\346\236\227/\345\233\276\347\211\207/\351\223\266\350\241\214\345\215\241\344\277\241\346\201\257.png" diff --git "a/46\350\265\226\346\235\260\346\236\227/\347\254\224\350\256\260/2022.9.5--\345\261\200\351\203\250\345\217\230\351\207\217\344\273\245\345\217\212\350\214\203\345\274\217.md" "b/46\350\265\226\346\235\260\346\236\227/\347\254\224\350\256\260/2022.9.5--\345\261\200\351\203\250\345\217\230\351\207\217\344\273\245\345\217\212\350\214\203\345\274\217.md" new file mode 100644 index 0000000000000000000000000000000000000000..4b416c5886a2cc6c7e02b2fb8a8205615d074840 --- /dev/null +++ "b/46\350\265\226\346\235\260\346\236\227/\347\254\224\350\256\260/2022.9.5--\345\261\200\351\203\250\345\217\230\351\207\217\344\273\245\345\217\212\350\214\203\345\274\217.md" @@ -0,0 +1,247 @@ +### 一,局部变量(==declare==) + +#### 1,声明 + +* 使用declare语句定义,并且指定变量的数据类型 +* 使用set或select语句初始化变量 +* **局部变量必须以‘’@‘’开头,必须先声明后使用** + +#### 2,格式 + +```sql +declare @变量名 变量类型[,@变量名 变量类型...] + +``` + +* **变量类型可以是SQL Server支持的所有数据类型,但对于局部变量text,ntext,image数据类型无效** +* 局部变量是字符型,则一定要在变量类型中指明最大长度(否则系统认为其长度为1) +* 局部变量不能使用‘’变量‘’=‘’变量值‘’ + + + +##### (1)初始化;(==select或set==) + +```sql +select @局部变量=变量值 +set @局部变量=变量值 +``` + +* ==select可以同时为多个变量赋值== + + ```sql + declare @变量名1 变量类型1[,@变量名2 变量类型2,@变量名3 变量类型3...] + select @变量名1=变量值1,@变量名2=变量值2,@变量名3=变量值3.... + ``` + +* ==set一次只能给一个变量赋值== + + ```sql + declare @变量名1 变量类型1[,@变量名2 变量类型2,@变量名3 变量类型3...] + set @变量名1=变量值1 + set @变量名2=变量值2 + set @变量名3=变量值3.... + ``` + + + +##### (2)局部变量输出(==select或print==) + +```sql +select @局部变量[,局部变量...] +print @局部变量 +``` + +##### (3)局部变量作用域 + +* 可以引用该变量的Transact-SQL语句的范围,变量的作用域从声明变量的地方开始到声明变量的批处理或储存过程的结尾 +* 变量也可以作用于查询条件来完成对数据表的查询,修改和删除 + + + +### 二,全局变量 + +* 系统内部的变量,用户无法定义与赋值 +* 作用范围并不局限某一程序,任何程序均可随意调用 +* 通常储存一些SQL Server的配置设置值 +* **全局变量名字前要有两个‘’@@‘’** +* 不能定义与全局变量同名的局部变量 + +#### 1,全局变量的符号及其功能 + +| 全局变量 | 功能 | +| ----------------- | -------------------------------------------------------- | +| @@CONNECTIONS | 最近一次启动以来登录或试图登录的次数 | +| @@CPU_BUSY | 最近一次启动以来CPUServer的工作时间 | +| @@CURRSOR_ROWS | 返回在本次连接最新打开的游标中的行数 | +| @@DATEFIRST | 返回SETDATEFIRST参数的当前值 | +| @@DBTS | 当前数据库中Timestamp数据类型的当前值 | +| @@ERROR | 系统生成的最后一个错误,若为0则成功 | +| @@FETCH_STATUS | 最近一条FETCH语句的标志 | +| @@IDENTITY | 保存最近一次的插入行的标识列的列值 | +| @@IDLE 自CPU | 服务器最近一次启动以来的累计空闲时间 | +| @@IO_BUSY | 自CPU服务器最近一次启动以来服务器输入/输出操作的累计时间 | +| @@LANGID | 当前使用的语言的ID | +| @@LANGUAGE | 当前使用语言的名称 | +| @@LOCK TIMEOUT | 返回当前锁的超时设置 | +| @@MAX_CONNECTIONS | 同时与SQL Server相连的最大连接数量 | +| @@MAX_PRECISION | 十进制与数据类型的精度级别 | +| @@NESTLEVEL | 当前调用存储过程的嵌套级,范围为0~16 | +| @@OPTIONS | 返回当前SET选项的信息 | +| @@PACK RECEIVED | 所读的输入包数量 | +| @@PACKET_SENT | 所写的输出包数量 | +| @@PACKET_ERRORS | 读与写数据包的错误数 | +| @@RPOCID | 当前存储过程的ID | +| @@REMSERVER | 返回远程数据库的名称 | +| @@ROWCOUNT | 最近一次查询涉及的行数 | +| @@SERVERNAME | 本地服务器名称 | +| @@SERVICENAME | 当前运行的服务器名称 | +| @@SPID | 当前进程的ID | +| @@TEXTSIZE | 当前最大的文本或图像数据大小 | +| @@TIMETICKS | 每一个独立的计算机报时信号的间隔(ms)数 | +| @@TOTAL_ERRORS | 读写过程中的错误数量 | +| @@TOTAL_READ | 读磁盘次数 | +| @@TOTAL_WRITE | 写磁盘次数 | +| @@TRANCOUNT | 当前用户的活动事务处理总数 | +| @@VERSION | 当前SQL Server的版本号 | + +# 范式 + +#### **Ⅰ**第一范式(1NF): + +数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、[实数](https://baike.baidu.com/item/实数?fromModule=lemma_inlink)、字符型、逻辑型、日期型等。 + +定义:如果一个关系模式R的所有属性都是不可分的基本[数据项](https://baike.baidu.com/item/数据项?fromModule=lemma_inlink),则R属于1NF。 + +例如,下面的数据库表是符合第一范式的: + +字段1 字段2 字段3 字段4 + +而这样的数据库表是不符合第一范式的: + +字段1 字段2 字段3 字段4 + +字段3.1 字段3.2 + +很显然,在当前的任何[关系数据库管理系统](https://baike.baidu.com/item/关系数据库管理系统?fromModule=lemma_inlink)(DBMS)中,谁也不可能做出不符合第一范式的数据库,因为这些DBMS不允许你把数据库表的一列再分成二列或多列。因此,想在现有的DBMS中设计出不符合第一范式的数据库都是不可能的。 + +#### **Ⅱ** 第二范式(2NF): + +数据库表中不存在非关键字段对任一[候选关键字](https://baike.baidu.com/item/候选关键字?fromModule=lemma_inlink)段的[部分函数依赖](https://baike.baidu.com/item/部分函数依赖?fromModule=lemma_inlink)(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况),也即所有非关键字段都完全依赖于任意一组候选关键字。 + +假定选课关系表为SelectCourse(学号,姓名,年龄,课程名称,成绩,学分),关键字为组合关键字(学号,课程名称),因为存在如下决定关系: + +(学号,课程名称) → (姓名,年龄,成绩,学分) + +这个数据库表不满足第二范式,因为存在如下决定关系: + +(课程名称) → (学分) + +(学号) → (姓名,年龄) + +即存在组合关键字中的字段决定非关键字的情况。 + +由于不符合2NF,这个选课关系表会存在如下问题: + +(1) 数据冗余: + +同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。 + +(2) 更新异常: + +若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。 + +(3) 插入异常: + +假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。 + +(4) 删除异常: + +假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。 + +把选课关系表SelectCourse改为如下三个表: + +学生:Student(学号,姓名,年龄); + +课程:Course(课程名称,学分); + +选课关系:SelectCourse(学号,课程名称,成绩)。 + +这样的数据库表是符合第二范式的, 消除了数据冗余、更新异常、插入异常和删除异常。 + +另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。 + +#### **Ⅲ** 第三范式(3NF): + +在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的[传递函数依赖](https://baike.baidu.com/item/传递函数依赖?fromModule=lemma_inlink)则符合第三范式。所谓传递函数依赖,指的是如果存在"A → B → C"的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系: + +关键字段 → 非关键字段x → 非关键字段y + +假定学生关系表为Student(学号,姓名,年龄,所在学院,学院地点,学院电话),关键字为单一关键字"学号",因为存在如下决定关系: + +(学号) → (姓名,年龄,所在学院,学院地点,学院电话) + +这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系: + +(学号) → (所在学院) → (学院地点,学院电话) + +即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。 + +它也会存在数据冗余、更新异常、插入异常和删除异常的情况,读者可自行分析得知。 + +把学生关系表分为如下两个表: + +学生:(学号,姓名,年龄,所在学院); + +学院:(学院,地点,电话)。 + +这样的数据库表是符合第三范式的,消除了数据冗余、更新异常、插入异常和删除异常。 + +**Ⅳ**鲍依斯-科得范式(BCNF): + +在第三范式的基础上,数据库表中如果不存在任何字段对任一候选关键字段的[传递函数依赖](https://baike.baidu.com/item/传递函数依赖?fromModule=lemma_inlink)则符合BC范式。 + +假设仓库管理关系表为StorehouseManage(仓库ID,存储物品ID,[管理员](https://baike.baidu.com/item/管理员?fromModule=lemma_inlink)ID,数量),且有一个管理员只在一个仓库工作,一个仓库可以存储多种物品。这个数据库表中存在如下决定关系: + +(仓库ID,存储物品ID) →(管理员ID,数量) + +(管理员ID,存储物品ID) → (仓库ID,数量) + +所以(仓库ID,存储物品ID)和(管理员ID,存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系: + +(仓库ID) → (管理员ID) + +(管理员ID) → (仓库ID) + +即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。它会出现如下异常情况: + +(1) 删除异常: + +当仓库被清空后,所有"存储物品ID"和"数量"信息被删除的同时,"仓库ID"和"管理员ID"信息也被删除了。 + +(2) 插入异常: + +当仓库没有存储任何物品时,无法给仓库分配管理员。 + +(3) 更新异常: + +如果仓库换了管理员,则表中所有行的管理员ID都要修改。 + +把仓库管理关系表分解为二个关系表: + +仓库管理:StorehouseManage(仓库ID,管理员ID); + +仓库:Storehouse(仓库ID,存储物品ID,数量)。 + +这样的数据库表是符合BCNF范式的,消除了删除异常、插入异常和更新异常。 + +#### **Ⅴ** 第四范式(4NF): + +关系模式R∈1NF,如果对于R对于R的每个非平凡多值依赖X→→Y(Y不属于X),X都含有候选码,则R∈4NF。4NF就是限制关系模式的属性之间不允许有非平凡且非函数依赖的多值依赖。显然一个关系模式是4NF,则必为BCNF。 + +#### **Ⅵ** 第五范式(5NF): + +是最终范式,消除了4NF中的连接依赖。 + +**VII** DK范式(DKNF):在值域上定义上的范式。 + +**VIII** 第六范式(6NF):目前关系型数据库最高范式。所有第六范式的关系同时满足第5范式与DK范式。 diff --git "a/46\350\265\226\346\235\260\346\236\227/\347\254\224\350\256\260/2022.9.6--\351\200\273\350\276\221\346\216\247\345\210\266.md" "b/46\350\265\226\346\235\260\346\236\227/\347\254\224\350\256\260/2022.9.6--\351\200\273\350\276\221\346\216\247\345\210\266.md" new file mode 100644 index 0000000000000000000000000000000000000000..5d5c389f72c400a92f0df3f12767d2c67ee1f123 --- /dev/null +++ "b/46\350\265\226\346\235\260\346\236\227/\347\254\224\350\256\260/2022.9.6--\351\200\273\350\276\221\346\216\247\345\210\266.md" @@ -0,0 +1,172 @@ +## 变量与逻辑控制 + +### 变量 + +#### 局部变量 + +局部变量必须以标记@作为前缀 ,如@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:返回当前会话的当前锁定超时设置(毫秒) +``` + +## 选择结构 + +单分支:if 双分支:if-else, 嵌套if + if 条件 begin 语句 end + +```sql +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 +``` + + + +## 输出语句 + +1. print变量或表达式 +2. select变量或表达式 + +```sql +--例: + print '数据库服务器名:' + @@servicename + select 15*8 +``` + + + +#### 使用convert函数 + +​ 由于PRINT 命令向客户端返回一个结果的字符串的信息。如果变量值不是字符串的话必须先用数据类型转换函数 CONVERT 将其转换为字符串。 + +```sql +--显示自动编号 +print '当前自动编号的值:' + convert(varchar(10),@@IDENTITY) +``` + +## 逻辑控制语句 + +#### 循环控制语句 + +##### while:可以通过break和continue控制循环语句中的执行。 + + while break(跳出循环)、continue(跳出当前循环) +Oracle: LOOP while...LOOP, FOR..LOOP +mysql: repeat + +##### case 多分支语句 + +case when + +```sql +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 +``` + + + +## 总结 + +变量的使用。要先用DECLARE 关键字声明,然后用SET或SELECT赋值。局部变量前必须有 “@” 作前缀,全局变量必须有 “@@” 作前缀。 +变量的输出可以用:PRINT或SELECT语句。 +逻辑控制语句提供了条件操作所需的顺序和逻辑。 +了解T-SQL编写工具。 +批处理可以提高语句执行的效率,使用“GO”作为结束标志。 \ No newline at end of file diff --git "a/46\350\265\226\346\235\260\346\236\227/\347\254\224\350\256\260/2022.9.7--\345\255\220\346\237\245\350\257\242.md" "b/46\350\265\226\346\235\260\346\236\227/\347\254\224\350\256\260/2022.9.7--\345\255\220\346\237\245\350\257\242.md" new file mode 100644 index 0000000000000000000000000000000000000000..6e13ec955648dbbdf375e1856f3f47b682a09b3c --- /dev/null +++ "b/46\350\265\226\346\235\260\346\236\227/\347\254\224\350\256\260/2022.9.7--\345\255\220\346\237\245\350\257\242.md" @@ -0,0 +1,135 @@ +# 子查询 + +​ 子查询是本质上就是一个完整 的SELECT 语句,它可以使一个 SELECT、SELECT...INTO 语句、INSERT...INTO 语句、DELETE 语句、或 UPDATE 语句或嵌套在另一子查询中。子查询的输出可以包括一个单独的值(单行子查询)、几行值(多行子查询)、或者多列数据(多列子查询)。 + +## 语法结构 + +可用四种种语法来创建子查询: + +1.带有比较运算符的子查询(sqlstatement) + +comparison(>,<,=,!=) + +2.带有ANY(some)或ALL谓词的子查询 + +comparison [ANY | ALL | SOME] (sqlstatement) + +3.带有谓词IN的子查询 + +expression [NOT] IN (sqlstatement) + +4.带有EXISTS谓词的子查询 + +[NOT] EXISTS (sqlstatement) + +### IN子查询 + +在嵌套查询中,子查询的结构往往是一个集合,所以谓词 IN是嵌套查询中最经常使用的谓词。 + +如查询与“刘晨”同一个系学习的学生。先要确定刘晨所在系名,在用它来查找所在在这个系中学习的学生。 + +SELECT 学号,姓名,系名 + +FROM 学生表 + +WHERE系名 IN + +(SELECT 系名 + +FROM 学生表 + +WHERE 姓名=“刘晨”) + +本例中,子查询的查询条件不依赖于父查询,称为不相关子查询。 + +用 IN 谓词,只能在主查询检索那些记录,在子查询中的某些记录也包含和它们相同的值。相反,可用 NOT IN 在主查询中检索那样的记录,在子查询中没有包含与它们的值相同的记录。下列示例返回有比 25%更低 的折扣的所有产品: + +SELECT * FROM Products + +WHERE ProductID NOT IN + +(SELECT ProductID FROM OrderDetails + +WHERE Discount >= .25); + +### 比较运算符 + +带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行连接。当用户确切知道内层查询返回单个值时,可以用>、<、=、>=、<=、!=或<>等比较运算符。 + +例如上面的那个查询,由于一个学生只可能在一个系学习,也就是说内查询的结果是一个只,因此可以用=代替IN:SELECT 学号,姓名,系名 + +FROM 学生表 + +WHERE 系名 = + +(SELECT 系名 + +FROM 学生表 + +WHERE 姓名=“刘晨”) + +还可用子查询中的表名别名来查询子查询外的 FROM 子句的列表。下列示例返回工资等于或高于所有职位相同员工的平均工资的员工姓名。这张员工表的别名为 "T1": + +SELECT LastName, + +FirstName, Title, Salary + +FROM Employees AS T1 + +WHERE Salary >= + +(SELECT Avg(Salary) + +FROM Employees + +WHERE T1.Title = Employees.Title) Order by Title; + +上例中AS保留词可选。如果子查询的查询条件依赖于父查询,这类子查询称为相关子查询,整个查询语句称为相关嵌套语句。 + +某些子查询在交叉表查询中是允许的,特别是谓词(那些在 WHERE 子句中的)。将子查询作为输出(那些列在 SELECT 中的)在交叉表查询中是不允许的。 + +### ANY子查询 + +子查询返回单值可以用比较运算符,但返回多值时要用ANY(有的系统用SOME)或ALL谓词修饰符。而使用ANY或ALL谓词的时候必须同时使用比较运算符。其语义如下: + +\>ANY 大于子查询结果中的某个值 + +\>ALL 大于子查询结果中的所有值 + +=ANY 大于等于子查询结果中的某个值 + +\>=ALL 大于等于子查询结果中的所有值 + +<=ANY 小于等于子查询结果中的某个值 + +<=ALL 小于等于子查询结果中的所有值 + +=ANY 等于子查询结果中的某个值 + +=ALL 等于子查询结果中的所有值 + +!=(或<>)ANY 不等于子查询结果中的某个值 + +!=(或<>)ALL 不等于子查询结果中的所有值 + +ANY 或 SOME 谓词,它们是同义字,来检索主查询中的记录,这些记录要满足在子查询中检索的任何记录的比较条件。下列示例将返回全部单价比任何以 25% 或更高的折扣卖出的产品高的产品: + +SELECT * FROM Products + +WHERE UnitPrice > ANY + +(SELECT UnitPrice FROM OrderDetails + +WHERE Discount >= .25); + +使用 ALL 谓词只检索主查询中的这些记录,它们满足在子查询中检索的所有记录的比较条件。如果将前一个示例中的 ANY 改为 ALL,查询只会返回单价比全部以 25% 或更高的折扣卖出的产品高的产品。这是更多的限制。 + +### EXISTS子查询 + +在 true/false 比较中使用 EXISTS 谓词(与可选的 NOT 保留字一道)来决定子查询是否会返回任何记录。 [2] EXISTS代表存在量词ヨ,带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值"false"。 + +可以利用EXISTS来判断x∈S、S⊆R、S=R、S∩R非空等是否成立。 \ No newline at end of file