diff --git "a/36\345\210\230\345\200\251\345\200\251/SQL\347\254\224\350\256\260.md" "b/36\345\210\230\345\200\251\345\200\251/SQL\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..0140cb24fd0a51e6e7467b9c51c978b9f4539c2f --- /dev/null +++ "b/36\345\210\230\345\200\251\345\200\251/SQL\347\254\224\350\256\260.md" @@ -0,0 +1,806 @@ +## 数据库基础 + +### 1.数据库 + +#### 1)创建数据库 + +```sql +-- create database 数据库名称; + +create database Stu; +``` + + + +#### 2)使用数据库 + +```sql +-- use 数据库名称; + +use Stu; +``` + + + +#### 3)删除数据库 + +```sql +-- drop database 数据库名称; + +-- 数据库使用中不可删,若要删除,则要切换到别的库,一般切换到主库master + +drop database Stu; +``` + + + +#### 4)扩展 + +```sql +use master; +go; +drop database Stu; +go; +create database Stu; +go; +use database Stu; +``` + + + +### 2.数据表 + +#### 1)创建数据表 + +```sql +-- create table 数据表名称 (列名1 数据类型 (约束),列名2 数据类型 (约束),......); + +create table student ( + stuname nvarchar(50), + stuage int +); +``` + + + +#### 2)删除数据表 + +```sql +-- drop table 数据表名称; + +drop table student; +``` + + + +#### 3)修改列表结构 + +```sql +-- alter table 表名; +-- alter column 列名 类型(约束); + +-- 列名不可改,改的是类型(类型为修改后的) + +alter table student; +alter column stuname varchar(50); +``` + + + +#### 4)扩展 + +##### (1)数据类型 + + 整型:int + + 字符串:nvarchar(50),varchar(50),ntext,text + + 浮点型:float,decimal(n,m) + + 日期:date,time,datetime + + 货币:money + + + +##### (2)属性 + +主键:primary key + +唯一识别表中的一条及记录(插入数据时,主键字段不能为空,重复) + + + +外键:foreign key (外键字段) references 参照表名 (参照表外键) + +使用外键建立两张表的联系,使值引用有效 + + + +自增:identity(x,y) + +x:自增起始值 y:自增增加值 + +通常用于业务主键,每插入一条记录自增y + + + +唯一:unique + +插入数据时不能重复 + + + +非空:not null + +插入数据时不能为空 + + + +默认值:default 'x' + +插入数据时,没有值时,系统会默认显示的值 + + + +检查条件:check (条件语句) + +条件语句例子(sex='男' or/and sex='女') + + + +分批处理:go + +先处理执行sql的语句,再处理执行sql后面的语句 + + + +## 增 + +### 插入数据 + +```sql +-- insert into 表名 (列名1,列名2,...) values (值1,值2,...),...... + +-- 列名和值:数量,数据类型,顺序一一对应 + +insert into student(stuname,stuage) +values +('刘倩倩',18), +('韦万炎',29) +``` + + + +## 删 + +### 删除数据 + + + +```sql +-- delete from 表名 where 条件表达式 + +delete from student -- 删除整张表 +where +-- 删除部分内容 +``` + + + +## 改 + +### 修改数据 + + + +```sql +-- update 表名 set 列名1='值1',列名2='值2' where 条件 + +-- 输入的值是修改后的 + +update student +set stuage=19,stuage=20 +where stuname='刘倩倩',stuname='韦万炎' +``` + + + +## 查 + + + +select [top n (percent 百分比)/(distinct 去重)] 列名1,... from 表名 + +[where 条件] + +[group by 字段] + + [order by 排序字段 (asc/desc)] + +[having 条件] + +### 1.查询单表的所有数据 + +```sql +-- select * from 表名; + +-- * 所有列,from 指明了查询表 + +select * from student; +``` + + + +### 2.查询指定列 + +```sql +-- select 列名1,... from 表名; + +select stuname from student; +``` + + + +#### 给列名设置别名 + +(1) 列名 别名 + +(2) 列名 as 别名 + +(3) 别名 = 列名 + +```sql +select stuname 姓名 from student +select stuname as 姓名 from student +select 姓名=stuname from student +``` + + + +### 3.查询若干数据 + +```sql +-- select top x * from 表名; + +-- top 获得查询结果的前 x 行 + +select top 2 * from student; +``` + + + +### 4.查询结果去除重复项 + +```sql +-- select distinct 列名1... from 表名; + +-- distinct 不同的 + +select distinct stuname from student; +``` + + + +### 5.对查询结果进行运算 + +```sql +-- select * from 表名 order by 排序字段 [asc 升序/ desc 降序] + +select * from student +order by stuage asc +``` + + + +### 6.查询时,列名可以进行运算 + +```sql +-- select 列1+列2 from student + +select stuname+'的年龄为:'+stuage from student +``` + + + +### 7.聚合查询 + +在查询语句中使用聚合函数 + +聚合函数:将一组数据进行统计计算,返回一个单值 + +字段: + +count 计数,计算非空值数据的个数(null不列入计算) + +sum 和,avg 平均,max 最大值,min 最小值 + +注意: + +select 子句中有聚合函数,那么其他表的列名除非是group by子句后的分组字段,不能有其他 + +```sql +-- select 列名1,字段(列名2) 备注名 from 表名 +-- where 条件表达式,对数据表原有数据进行筛选,不包括聚合 +-- group by 分组字段... +-- having 包含聚合,对分组后的字段过滤 +-- order by 排序字段 [asc/desc] + +select stuname,avg(stuage) 平均年龄 from student +group by stuname +having avg(stuage)>18 +``` + + + +### 8.多表查询 + +当查询的数据字段涉及多张表时需要到多表连接查询 + +#### 1)内连接 + +```sql +-- select * from 表名1 [inner] join 表2 on 表1.列 = 表2.列 + +-- inner 可以省略, 表2 为主表, 需满足连接条件才会返回结果 + +select * from class +join student on class.studendid=student.id +``` + + + +#### 2)外连接 + +不满足连接条件的记录,另一张表将以null填充返回连接记录 + +##### (1)左外连接 + +```sql +-- select * from 表名1 left join 表2 on 表1.列 = 表2.列 + +-- 表1 为主表,表2 为次表 + +select * from student +left join class on class.studendid=student.id +``` + + + +##### (2)右外连接 + +```sql +-- select * from 表名1 right join 表2 on 表1.列 = 表2.列 + +-- 表1 为次表,表2 为主表 + +select * from class +right join student on class.studendid=student.id +``` + + + +##### (3)全外连接 + +```sql +-- select * from 表名1 full join 表2 on 表1.列 = 表2.列 + +select * from class +full join student on class.studendid=student.id +``` + + + +### 9.自连接查询 + +如果在一个连接查询中,涉及到的两个表都是同一个表,这种查询称为自连接查询。 + +```sql +-- select 要查询的列 from 表1 join 表2 on 表1.列 = 表2.列 where 条件语句 + +select S1.stuid,S1.stuname 表1姓名,S2.stuname 表2姓名 from student S1 +join student S2 on S1.stuid=S2.stuid +where S1.stuname=S2.stuname +``` + + + +### 10.子查询 + +#### 1)子查询作为虚拟表 + +```sql +-- select * from (select 列名 from 表名) '别名' + +-- 使用子查询查询 软件一班的每个学生 的平均分(聚合查询 + 子查询 + 分组) +select StudentName 姓名, avg(总分/3) 平均分 from +(select studentid, sum(Score) 总分 from Score group by studentid) 分数 +join Student on 分数.StudentId=Student.StudentId +where classid=1 +group by StudentName +``` + + + +#### 2)子查询作为条件 + +##### (1)比较运算符连接条件 + +比较运算符连接条件 >=, <= , > ,< ,!= ,<> 子查询必须返回一行一列的值 + +```sql +-- 查询成绩比平均成绩低的成绩信息 +select * from Scores +where Score<(select avg(Score) from Scores) +``` + + + +##### (2)in,not in 连接条件 + +子查询结果集只能是一列 + +1. in关键词,表示在什么值内的意思。not in 表示不在什么值内 +2. in、not in后面的select语句只能有一列。 + +```sql +-- select * from 表名 where 列 in/not in (select 指定列 from 表名 ...) + +-- 查询钟琪和曾小林的考试成绩: +select * from Score +where StudentId in +(select StudentId from Student where StudentName='钟琪' or StudentName='曾小林'); +-- 子查询中也可以使用in: +select * from Score +where StudentId in +(select StudentId from Student where StudentName in ('钟琪', '曾小林')); +``` + + + +##### (3)exists,not exists 连接条件 + +```sql +-- 查询有成绩的学生信息:学号,姓名 +select StudentId,StudentName from Student where exists(select * from Score where Score.StudentId=Student.StudentId) +-- 查询出没有成绩的学生信息:学号,姓名 +select StudentId,StudentName from Student where not exists(select * from Score where Score.StudentId=Student.StudentId) +``` + + + +##### (4)any, all连接条件 + +any(和子查询返回的某个值比较),all(和子查询返回的所有值比较) + +```sql +-- 查询出成绩比课程编号1的所有成绩都高的成绩信息 +select * from Score where score>all(select * from Score where CourseId=1) +-- 查询出成绩比课程编号1的任意一个成绩高的成绩信息 +select * from Score where score>any(select * from Score where CourseId=1) +``` + + + +#### 3)子查询作为列 + +子查询作为列,子查询的结果只能返回一列 + +```sql +-- select 列1,(select...from...),列3 from ..... + +-- 查询学生的成绩信息:成绩编号,姓名,课程名称,成绩 +select ScoreId 成绩编号, +(select StuName from StuInfo where StuId=Scores.StuId) 姓名, +(select courseName from CourseInfo where CourseId=Scores.CourseId) 课程名称 , +Score 成绩 +from Scores +``` + + + +### 10.分页查询 + +```sql +-- select 列名... from 表1 order by 字段 [asc/desc] offset x rows fetch next y rows only + +-- 偏移x行,获取y行 order by 字段 为固定关键字 +``` + + + +## 扩展 + +### 1.where 条件表达式 + +#### 1)运算符 + +##### (1)比较运算符 + +大于:> + +小于:< + +大于等于:>= + +小于等于:<= + +不等于:!= <> + +```sql +select * from student +where stuage>18 +``` + + + +##### (2)逻辑运算符 + +and(与) + +or(或) + +not(非) + +```sql +select * from student +where stusex=1 and sruage>18 +``` + + + +##### (3)范围运算符 + +在【A,B】范围内:between A and B + +不在【A,B】范围内:not between A and B + +```sql +select * from student +where stuage between 18 and 21 +``` + + + +##### (4)列表运算符 + +in (值1,值2,...) + +not in (值1,值2,...) + +```sql +-- 查询出参加考试的学生的信息 +select * from stuinfo +where stuNo in (select stuID from stuMarks) +``` + + + +##### (5)空值运算符 + +is null 值为null返回结果记录 + +is not null 值不为null返回结果记录 + +null:插入数据时,没有给该字段赋值,也没有指向内存空间的地址 + +' ':空字符串,没有任何字符,有存储空间 + + + +##### (6)模式匹配运算符 + +like '模式字符串' + +匹配字符: + +%:匹配0~n任意字符 + +_:匹配1个任意字符 + +[a,b,c,...]:匹配指定列表中的一个字符 + +[^a,b,c,...]:不匹配指定列表中的字符 + +```sql +-- select * from 表名 where 列名 like'' + +select * from student where stuname like'刘%' +``` + + + +### 2.日期函数 + +1)getdate() + +获取当前系统时间 + +2)year() + +函数截取时间的年份部分,返回的是整数类型 + +3)month() + +函数截取时间的月份部分,返回的是整数类型 + +4)day() + +函数截取时间的日期部分,返回的是整数类型 + +5)datepart(指定日期部分,日期时间) + +获取指定的日期部分,返回是一个整型;日期部分有年、月、日、周.................. + +6)dateName(指定日期部分,日期时间) + + 获取指定的日期部分,返回是一个字符串类型;日期部分有年、月、周.................. + +7)dateadd(指定日期部分,整数,日期时间) + +将日期时间的指定部分增加上整数值,返回的是一个日期时间类型。 + +8)datediff(指定日期部分,开始时间,结束时间) + +将结束时间-开始时间,返回的是的指定日期部分的差值,是一个整数类型。 + +```sql +-- 获取当前时间 +select getdate (列名) +-- 年份 +select year ('2003-11-27') +-- 月份 +select month(getdate()) +-- 日期 +select day() + +/* +select datepart(year,getdate()) 年份 -- year年份 +select datepart(month,getdate()) 月份 -- month月份 +select datepart(day,getdate()) 日期 -- day日期 +select datepart(dayofyear,getdate()) 一年中的第几天 -- day日期 +select datepart(weekday,getdate()) 星期数 +-- WEEKDAY 一周中的星期数;整数的星期,1代表星期日,2代表星期一,... +select datepart(week,getdate()) 一年中的第几周 -- WEEK一年中的周数 + +-- dateName(指定日期部分,日期时间),返回的是一个字符串 +select dateName(weekday,getdate()) 星期数 + +-- dateName(指定日期部分,日期时间),返回的是一个字符串 +select dateName(weekday,getdate()) 星期数 + +-- 日期增加函数,dateadd(指定日期部分,增加的整数值,要增加的日期时间) ,返回的是一个增加相应部分值的日期时间类型值 +select dateadd(year,10,getdate()) --距今10年后的时间 +select dateadd(month,10,getdate()) --距今10个月后的时间 +select dateadd(day,10,getdate()) --距今10天后的时间 +select dateadd(week,10,getdate()) --距今10周后的时间 + +-- 日期减法函数,datediff(指定日期部分,开始时间,结束时间),返回的是结束时间-开始时间的指定部分的差值,是一个整数类型 +select datediff(year,'2000-01-01',getdate()) +select datediff(month,'2000-01-01',getdate()) +select datediff(month,'2000-01-01',getdate()) +*/ +``` + + + +### 3.三范式 + +```sql +1. 第一范式:原子性,列不可拆分。设计的意义在于精确查找,避免like。 +2. 第二范式:表要有主键,列必须完全依赖于主键,而不能只依赖于主键的一部分。设计的意义避免数据太多冗余,修改麻烦。 +3. 第三范式:列必须直接依赖于主键,不能间接依赖。设计意义同第二范式。 +``` + + + +### 4.集合运算 + +#### 1)并集运算 union [all] + +[(如若去重则不加[all]) + +将两个或两个以上放入结果集合并成一个结果集,垂直合并 + -- 合并的所有结果集必须相同的列数,每列的数据类型一样 + -- 返回的结果集的列名标题由第一个结果集决定 + +#### 2)交集运算 intersect + +将多个结果集中相同的记录取出来形成新的集合 + +#### 3)减集运算 except + + (前面减后面) + +将前面的结果集减去后面结果集中相同记录,留取第一个结果集中不同的记录 + +```sql +-- select 列名 from 表1 +-- union / intersect / except +-- select 列名 from 表2 + +-- 并集,减集 的列名内容要一致 + +-- 查询落未获得英雄 +select store_hero 英雄 from store -- 全部英雄 +except +select store_hero 英雄 from hero -- 个人英雄 +join account_message on hero.yh_id=account_message.message_ID +join store on hero.hero_id=store.hero_id +where message_name='落' +``` + + + +### 5.窗口函数 + +同时具有分组(partition by)和排序(order by)的功能 + +不减少原表的行数,所以经常用来在每组内排名 + +#### 1)专用窗口函数 + +(1)连续排名 row_number (1 2 3 4 5 ) + +(2)并列跳跃排名 rank (1 1 3 3 5 ) + +(3)并列连续排名 dense_rank (1 1 2 2 3 ) + +```sql +-- 窗口函数 over (partition by 分组的列名 order by 排序的列名) + +-- 查询每门课程的成绩排名,成绩由高到底 +select *, +row_number() over (partition by courseid order by score desc) as row_num, +rank() over (partition by courseid order by score desc) as ranking, +dense_rank() over (partition by courseid order by score desc) as dese_rank +from Scores +``` + + + +#### 2)聚合函数 + +sum. avg, count, max, min + +见7.聚合查询 + + + +### 6.转换函数 + +#### 1)cast (表达式 as 目标数据型) + +用于将某种数据类型的表达式显示转换为另一种数据类型 + +```sql +cast ( expression as data_type [ ( length ) ] ) +-- expression表达式,待转换的数据 +-- as 关键字 +-- data_type 转换的目标数据类型。length带长度的数据类型需要,如字符串 +``` + + + +#### 2)convert + +可以按照指定的格式将数据转换为另一种数据类型,优点是可以格式化日期和数值 + +```sql +convert ( data_type [ ( length ) ] , expression [ , style ] ) +-- data_type 转换的目标数据类型。length带长度的数据类型需要,如字符串 +-- expression表达式,待转换的数据 +-- style 转换数据格式的代码 +``` + + + +### 7.数学函数 + +#### 1)生成随机数 + +rand ( ) : flost [ ) + +#### 2)生成唯一标识符 + +newid ( )