目录

  • 1.SQL语言的功能
  • 2.SQL支持的数据类型
    • 1.精确数值型
    • 2.近似数字
    • 3.日期时间类型
    • 4.字符串类型
    • 1.普通字符编码串
    • 2.统一字符编码串
    • 5.二进制字符串类型
    • 6.其它类型
    • 7.总结
  • 3.SQL语言
    • 1.数据查询
      • 1.单表查询
        • 1.日期函数使用
        • 2.WHERE子句查询
        • 3.模糊查询LKE
        • 4.对查询结果进行排序
        • 5.使用聚合函数进行统计
        • 6.对数据进行分组
      • 2.多表链接查询
        • 1.内链接[使用ANSI标准为例]
        • 2.自链接
        • 3.外链接
        • 4.TOP的使用
      • 3.CASE表达式
        • 1.CASE简介
        • 2.CASE应用示例
      • 4.将查询结果保存到表中
      • 5.子查询
        • 1.使用子查询进行基于集合的测试
        • 2.使用子查询进行比较测试
        • 3.使用子查询进行基于集合的测试
        • 4.带EISTS谓词的子查询
      • 6.查询的集合运算
    • 2.视图
      • 1.视图概述
      • 2.视图定义和使用
      • 3.视图的修改与删除
    • 3.数据更改功能
      • 1.数据的插入
      • 2.数据更新
      • 3.数据删除
    • 4.数据控制功能
      • 1.授权
      • 2.回收授权
      • 3.拒权
    • 5.索引
      • 1.概念
      • 2.存储结构及分类
        • 1.聚集索引
        • 2.非聚集索引
      • 3.创建和删除索引

1.SQL语言的功能

SQL功能 谓词
数据定义DDL CREATE, DROP, ALTER
数据查询DQL SELECT
数据操作DML INSERT, UPDATE, DELETE
数据控制DCL GRANT, REVOKE, DENY

2.SQL支持的数据类型

1.精确数值型

数据类型 描述 存储
tinyint 0~255 1字节
smallint -32768~32767 2字节
int -21 4748 3648 ~ 21 4748 3647 4字节
bigint -922 3372 0368 5477 5808 ~ 922 3372 0368 5477 5807 8字节
decimal(p, s)或numeric(p, s) -1038+1 ~ 1038 , p是最大位数【1~38之间】默认是18;s:小数点右侧存储的最大位数,s必须是0~p之间的值,默认是0 5-17字节
smallmoney -21 4748.3648 ~ 21 4748.3647 4字节
momey -922 3372 0368 5477.5808 ~ 922 3372 0368 5477.5807 8字节

smalint, decimal会用即可

2.近似数字

数据类型 描述 存储
float(n) -1.79E+308~1.79E+308。n:24保存4字节;53:就保存8字节 4/8字节
real -3.04E+38~3.4E+38 4字节

一般使用float

3.日期时间类型

数据类型 描述 存储
datetime 1753.1.1~9999.12.31, 精度3.33ms 8字节
datetime2 1753.1.1~9999.12.31, 精度100ns 6~8字节
smalldatetime 1900.1.1~2079.6.6, 精度1min 4字节
date 进存储日期,0001.1.1~9999.12.31 3字节
time 仅存储时间, 精度100ns 3~5字节
datatimeoffset 与datetime2相同,外加时区偏移 8~10字节
tiemstamp 存储唯一的数字, 每当创建或修改某行时,该数字会更新,timestamp基于内部时钟,不针对真实时间,每个标志能有一个timestamop变量

4.字符串类型

1.普通字符编码串

数据类型 描述 存储
char(n) 固定长度字符串,0~8000个字符 n字节
varchar(n) 可变长度,0~8000个字符 由实际长度决定
varchar(max) 可变长度字符串,0~1 0737 41824个字符 由实际长度决定
text 可变长度的字符串,最多2GB字符数据 由实际长度决定

2.统一字符编码串

此处省略
只需要在普通编码字符串的数据类型前加上一个n即可实现统一的Unicode格式的编码,存储长度除了ntext不变以外,其余均减半
举例:

数据类型 描述 存储
nchar(n) 固定长度字符串,0~4000个字符 n字节

总结:以后的实际应用中只考虑使用统一编码何时规范即可,

5.二进制字符串类型

数据类型 描述 存储
bit 允许0, 1, NULL
binary(n) 固定长度二进制数据,0~8000B nB
varbinay(n) 可变长度二进制数据,0~8000B 由实际长度决定
varbinay(max) 可变长度二进制数据,0~2GB 由实际长度决定
image 可变长度二进制数据,0~2GB 由实际长度决定

对于双属性的元素比如人的性别,图书的借还等可以设置bit来节约空间

6.其它类型

数据类型 描述
sql_variant 存储最多8000字节不同数据类型的数据, 除了text, ntext,以及timestamp
uniqueidetifier 存储全局标识符(GUID)
xml 存储XML格式化数据,0~2GB
cursor 存储对于数据库操作的指针的引用
table 存储结果集,共稍后处理

二进制数据类型接触的比较少,所以了解即可

7.总结

以上内容是笔者将书中的全面内容搬运过来,做了稍加的整理和解释说明。以后的开发中也用不到这么多的种类,因此不必全部都学会但是一定要有了解,知道用的时候选择什么样的数据类型最合适。

比如说生活中的小数据:全国新冠疫情疫苗接种人数就用int,银行必须使用decimal类型、因为客户数据重要,需要用到大内存的数据类型,全国人口的出生数据记录,为了日后能继续使用因此需要设置为datetime或者datetime2即可,两者之时精度不同罢了。。。

3.SQL语言

数据准备
创建 Student 表结构

列名 含义 数据类型 约束
Sno 学号 char(6) 主键
Sname 姓名 非空
Ssex 性别 nvarcahr(20) 非空;默认为男;检查只能是"男"或"女"
Sbirthday 出生日期 smalldatetime
Sdept 所在系 nvarchar(20)
Memo 备注 text
CREATE DATABASE StuUSE Stu--创建学生表
CREATE DATABASE StuUSE Stu--创建学生表
CREATE TABLE Student(Sno CHAR(6) PRIMARY KEY,Sname NCHAR(20) NOT NULL,Ssex NCHAR(2) NOT NULL DEFAULT '男' CHECK (Ssex IN ('男', '女')),Sbirthday SMALLDATETIME,Sdept NVARCHAR(20),Memo text
)

创建 Course 表结构

列名 含义 数据类型 约束
Cno 课程号 char(3) 主键
Cname 课程名 nvarchar(20) 非空
PreCno 先修课程号 char(3)
Credit 学分 tinyint
Semester 开课学期 tinyint
--创建Course表
CREATE TABLE Course
(Cno CHAR(3) PRIMARY KEY,Cname NVARCHAR(20) NOT NULL,PreCno CHAR(3),Credit TINYINTSemester TINYINT,
)

创建 SC 结构

列名 含义 数据类型 约束
Sno 学号 char(6) 主键,外键
Cno 课程号 nchar(20) 主键,外键
Grade 成绩 smallint 检查:成绩[0,100]
--创建SC表
CREATE TABLE SC
(Sno CHAR(6),Cno NCHAR(20),Grade SMALLINT CHECK (BETWEEN 0 AND 100)CONSTRAINT PK_sno_cno PRIMARY KEY (Sno, Cno),CONSTRAINT FK_sno FOREIGN KEY(Sno) REFERENCES Student(Sno)
)

在创建主外键的时候需要注意类型一致和形参一致
SC表的Sno字段要和Student表的Sno保持一致

-- 插入Student数据
INSERT INTO Student VALUES
(('060101', '钟文辉', '男', '1997-05-01', '计算机系', '又系毕业生'),('060102', '吴细文', '女', '1997=03-24', '计算机系', '爱好:音乐'),('060103', '吴朝西', '男', '1998-07-01', '计算机系', ''),('070101', '王冲瑞', '男', '1998-05-04', '机电系', '爱好:音乐')('070102', '林滔滔', '女', '1997-04-03', '机电系', '爱好:体育'),('070103', '李修雨', '女', '1996-03-03', '机电系', ''),('070301', '李奇', '男', '1998-09-17', '信息管理', '')
)--插入 Course数据
INSERT INTO Course VALUES
(('C01', '高等数学', '', 4, 1),('C02', '程序设计', '', 4, 2),('C03', '数据结构', 'C02', 3, 3),('C04', '数据库原理', 'C03', 3, 4),('C05', '音乐欣赏', '', 1, 4),('C06', '大学物理', 'C01', 4, 2),('C07', '计算机网络', 'C02', 2, 4)
)--插入SC数据
INSERT INTO  SC VALUES
(('060101', 'C01', 91),('060101', 'C03', 88),('060101', 'C04', 95),('060101', 'C05'),('060102', 'C02', 81),('060102', 'C03', 76),('060102', 'C04', 92),('070101', 'C01', 50),('070101', 'C03', 86),('070101', 'C04', 90),('070101', 'C05'),('070103', 'C04', 52),('070103', 'C06', 47),('070301', 'C03', 87),('070301', 'C04', 93)
)

1.数据查询

1.单表查询

1.日期函数使用

把需要查询的列名加上即可或者用通配符 * 来代替所有列名
select 查询字段可以是表中存在的列也可以是表达式,常量或者函数

示例1:YEAR()和GETDATE()函数使用


SELECT Sname, YEAR(GETDATE())-YEAR(Sbirthday) FROM Student

YEAR():把当前出绳子断转为年
GETDATE():得到当前年

【AS别名】
示例2:AS可以省略


SELECT Sname 姓名,
YEAR(GETDATE()) - YEAR(Sbirthday) 年龄,
'今年是' 今年是,
YEAR(GETDATE()) 年份FROM Student

2.WHERE子句查询

BETWEEN…AND

查询条件 谓词
关系运算符 <, <=, ==, <>, !=, >=, >
确定范围 BETWEEN…AND, NOT BETWEEN…AND【左闭右闭区间】
确定集合 IN, NOT IN
字符匹配 LIKE, NOT LIKE
空值 IS NULL, IS NOT NULL
多重条件 AND, OR

关于 NULL 带来的影响,关系运算符中只有 <> 可以正确的判断 NULL
最好习惯性使用 IS NULLIS NOT NULL 来对 NULL 值判断

OR优先级低于AND,因此在使用的时候需要使用()进行优先级区分

示例额3:查询在1997年出生的学生全部信息
日期也可以使用 BETWEEN…AND


SELECT * FROM Student WHERE Sbirthday BETWEEN '1997-01-01' AND '1997-12-31'

3.模糊查询LKE

字符 含义
- 匹配任意一个字符
% 匹配0个到多个字符
[] 表示匹配匹配abcdg字符中任意一个,如要连续匹配[b-d]用 ‘-’
[^] 不匹配任意一个字符, [^abcdg]表示不匹配abcdg任意一个字符;[^b-e]不匹配abcde这段连续字符中的任意一个字符

示例4:查询姓名第二个字是“冲”的学生信息


SELECT * FROM Student WHERE Sname LIKE '_冲%'

示例5:查询姓名“李”字开头的学生信息


SELECT * FROM Student WHERE Sname LIKE '李%'

示例6:查询学号最后一位是“2”或“3”的学生信息


SLECT * FROM Student WHERE Sno NOT LIKE '%[2,3]'

示例7:转义子符
ESCAPE:的使用


包含30%

SELECT * FROM Table WHERE filed LIKE '%30!%%' ESCAPE '!'

包含_

SELECT * FROM Table WHERE field LIKE '%!_%' ESCAPE '!'

4.对查询结果进行排序

关键字是:ORDER BY field DESC|ASC

升降/序 含义
DESC 降序
ASC 升序

5.使用聚合函数进行统计

函数 含义
COUNT 统计去重后的数据个数
SUM 累加和(必须是数值类型)
AVG 平均值(必须是数值类型)
MAX 得到列的最大值
MIN 得到列的最小值

统计函数中除(*)之外,其它函数在计算过程中忽略NULL值

统计函数的计算范围可以是满足WHERE字句条件的记录,也可以满足条件的组进行计算【分组的话需要使用HAVING函数】

6.对数据进行分组

带有 GROUP BY 子句的 SELECT 语句的查询列表中只能出现分组依据列和聚合函数。因为每组中除了这两类相同外,其余属性的值可能不唯一

示例1:统计每门课程的选课人数,列出课称号和选课人数


SELECT Cno 课称号, COUNT(Sno) 选课人数
FROM SC
GROUP BY Cno

执行过程分析:

  1. 首先对SC表的数据按照Cno的值进行分组,所有具有相同Cno值的元素归位一组
  2. 然后再对一组使用COUNT函数进行计算
  3. 最后求出每组的学生人数

示例2:统计每个学生的选课门数,列出学号,选课门数和平均成绩


SELECT Sno 学号, COUNT(Cno) 选课门数, AVG(Grade) 平均成绩
FROM Student
GROUP BY Sno

示例3:统计每个系的男女生人数,结果按系名的升序排序


SELECT Count(*) 人数
FROM Student
GROUP BY Sdept, Sex
ORDER BY Sdept

先按照系分组,在对系中的性别分组。从而把每个系中相同性别的人聚合在一起,最后在对每个最终分组结果进行统计
当有多个分组依据时,统计是以最小单位进行的

示例4:本题也可以使用WHERE进行分组,因为性别只有两个属性


SELECT Count(*) 男生人数
FROM Student
WHERE Sex='男'
GROUP BY Sdept

执行顺序

带有 WHERE 子句的分组查询是先执行 WHERE 子句的选择,得到结果后再进行分组统计

注意
使用 HAVING 子句对分组后的统计结果再进行筛选,功能有点像 WHERE 子句,但它用于组而不是单个记录。

HAVING 子句中可以使用聚合函数,但在 WHERE 子句中则不能

示例5:查询选课门数超过3门的学生的学号和选课门数


SELECT Sno, COunt(*) 选课门数
FROM SC
GROUP BY Sno
HAVING Count(*) > 3

执行过程

  1. 先执行 GROUP BY 子句对 SC 表数据按 Sno 进行分组
  2. COUNT(*) 分别对每一组进行统计
  3. HAVING 筛选出统计结果大于3的组

正确的理解 WHERE, GROUP BY, HAVING 子句的作用及执行顺序

  • WHERE:筛选FROM 子句中指定的数据源所产生的行数据
  • GROUP BY:筛选WHERW 子句筛选后的数据进行分组
  • HAVING:筛选GROUP BY 子句分组后的数据再进行筛选

如何优化?

执行GROUP BY分组之前首先使用 WHERE 对数据进行优化减少GROUP BY的数据分组行
最后利用 HAVING 在对分组后的数据进行筛选

示例6:查询“计算机系”和“机电系”每个系的学生人数,可以有如下两种写法


第一种

SELECT Sdept, COUNT(*) FROM Student
GROUP BY Sdept
HAVING Sdept in("计算机系", "机电系")

第二种

SELECT Sdept, COUNT(*) FROM Student
WHERE Sdept in("计算机系", "机电系")
GROUP BY Sdept

第二种执行效率比第一种高:因为分组的数据少

2.多表链接查询

1.内链接[使用ANSI标准为例]

非ANSI标准:链接操作写在WHERE子句中

-- 别名可要可不要【如果需要别名的话就按如下方式使用】
SELECT 字段 FROM 表1 别名1, 表2 别名2 WHERE 条件1 AND 条件2;

ANSI-SQL-92中:链接操作写在JOIN中

-- 别名可要可不要【如果需要别名的话就按如下方式使用】
SELECT 字段 FROM 表1 别名1 [INNER] JOIN 表2 别名2 ON 链接条件 AND 其他条件;

示例1:查询每个学生及其选课的详细信息


SELECT * FROM
Student INNER JOIN SC
ON Student.Sno=SC.Sno

解释

没有 ON Student.Sno=SC.Sno 则是获取 StudentSC 表的笛卡尔积【所谓笛卡尔积就是数学中的排列】
加上 ON Student.Sno=SC.Sno 之后就相当于对这个笛卡尔积进行 去重操作 即得到组合

示例2:查询每个学生及其选课的详细,要求去掉重复的列


SELECT S.Sno, Sname, Sex, Sbirthday, Sdept, Memo, Cno, Grade
FROM Student S INNER JOIN SC
ON S.Sno=SC.Sno

示例3:查询“计算机系”选修了“数据库原理”课程的学生成绩单,成绩单包含姓名,课程名称,成绩信息

SELECT Sname, Cname, Grade
FROM Student S INNER JOIN SC
ON S.Sno=SC.Sno
JOIN Course C
ON SC.Cno=C.Cno
WHERE Sdept='计算机系' AND Cname='数据库原理'

示例4:查询选修了“数据库原理”课程的学生姓名和所在系

SELECT Sname, Sdept
FROM Student INNER JOIN SC
ON S.Sno=SC.Sno

示例5:统计每个系的学生的平均成绩

SELECT Sdept, AVG(Grade) 系平均成绩
FROM Student S INNER JOIN SC
ON S.Sno=SC.Sno
JOIN Course C
ON SC.Cno=C.Cno
GROUP BY Sdept

示例6:统计“计算机系”学生中每门课程的选课人数,平均分布,最高分和最低分

SELECT Cno, COUNT(*) 选课人数 , AVG(Grade) 平均分, MAX(Grade) 最高分, MIN(Grade) 最低分
FROM Student S INNER JOIN SC ON S.Sno=SC.Sno
WHERE Sdept='计算机系'
GROUP BY Cno

2.自链接

有了上面内连接的基础,可以猜到自连接的本质就是自己和自己形成一个笛卡尔积

SELECT 字段 FROM 表1 AS T1 INNER JOIN 表1 AS T2 ON T1.列名=T2.列名

因此在使用自连接的时候一定要为表取别名
示例:查询课程“数据库原理”的先修课程名

SELECT C1.Cname 课程名, C2.Cname 先修课程名
FROM Course C1 JOIN Course C2
ON C1.PreCno=C2.Cno
WHERE C1.name='数据库原理'

示例2:查询与“钟文辉”在同一个系学习的学生的姓名和所在系

SELECT S2.Sname, S1.Sdept
FROM Student S1 JOIN Student S2
ON S1.Sdept=S2.Sdept
WHERE S1.Snam='钟文辉' AND S2.Sname != '钟文辉'

3.外链接

概念部分

  1. 外连接分为左外连接和右外连接
  2. 如果联合查询,左侧的表完全显示我们就说是左外连接;右侧的表完全显示就是右外连接
  3. 如果外连接也是在对表里做作笛卡尔积,则结果和内连接差不多
  4. 如果两个表里的数据都是一 一对应,此时内外连接是等价的,但是有时候可能存在一些数据没有对应关系,此时内外连接就有差别
-- 左外连接:表1完全显示
SELECT * FROM 表1 LEFT JOIN 表2 ON 连接条件
-- 右外连接:表2完全显示
SELECT * FROM 表1 RIGHT JOIN 表2 ON 连接条件

示例1:查询计算机系全体学生的选课情况

SELECT S.Sno, Sname, Sdept, SC.Sno
FROM Student S LEFT JOIN SC
ON S.Sno=SC.Sno
WHERE Sdept='计算机系'
ON S1.Sdept=S2.Sdept

示例2:查询没有人选的课程的课程名

SELECT Cname, Sno
FROM Course C LEFT JOIN SC
ON C.Cno=SC.Cno
WHERE SC.Cno IS NULL

这里的 NULL 需要使用 IS 来判断

示例3:统计“计算机系”每个学生的选课门数,应包含没有选课的学生

SELECT S.Sno 学号, COUNT(SC.Cno) 选课门数
FROM Student S LEFT JOIN SC
ON S.Sno=SC.Sno
WHERE Sdept='计算机系'
GROUP BY S.Sno

COUNT并不会对 NULL 进行计数

示例4:统计“机电系”选课门数少于3门的学生的学号和选课门数,包括没选课的学生,查询结果按选课门数降序排序

SELECT S.Sno 学号, COUNT(SC.Cno) 选课门数
FROM Student S LEFT JOIN SC
ON S.Sno=SC.Sno
WHERE Sdept='机电系"
GROUP BY S.Sno
HAVING COUNT(SC.Cno) < 3
ORDER BY (SC.Cno) DESC

执行顺序解析

  1. 执行连接操作FROM Student S LEFT JOIN SC ON S.Sno=SC.Sno
  2. 对连接的结果执行 WHERE进行筛选
  3. 执行 GROUP BY进行对步骤②的数据进行筛选
  4. 执行HAVING对步骤③的数据进行筛选
  5. 执行ORDER BY 对步骤④的数据进行筛选

4.TOP的使用

相当于MySQL的LIMIT的分页查询
示例1:查询学分最多的四门课程的课程名称,学分和开课时期

SELECt TOP 4 Cname, Credit, Semester
FROM Course
ORDER BY Credit DESC

示例2:查询选课人数最多的两门课程,列出课程号和选课人数

SELECT TOP 2 WITH TIES Cno, COUNT(*) 选课人数
FROM SC GROUP BY Cno
ORDER BY COUNT (Cno) DESC

如果在 TOP 子句中使用 WHIT TIES 谓词,则要求必须使用 ORDER BY 子句对查询结果进行排序,否则会语法报错

3.CASE表达式

1.CASE简介

CASE通俗易懂理解

  1. 运行过程类似于编程语言中的 switch选择功能,当WEHN后面的布尔表达式为真的时候就返回第一个CASE值。不会执行后续的WHEN判断
  2. 运行结果几乎和sql语言中的 AS别名一样,查询的结果有一个 THEN 后边的新的列名

示例1:查询全体学生信息,并对所在系用代码显示
假设:

  • 计算机系:CS
  • 机电系:JD
  • 信息管理系:IM

简单CASE表达式:

SELECR Sno 学号, Sname 姓名, Ssex 性别,
CASE Sdept
WHEN '计算机系' THEN 'CS'
WHEN '机电系' THEN 'JD'
WHEN '信息管理系' THEN 'IM'
END '所在系'
FROM Student

复杂CASE表达式:

SELECR Sno 学号, Sname 姓名, Ssex 性别,
CASE
WHEN Sdept = '计算机系' THEN 'CS'
WHEN Sdept = '机电系' THEN 'JD'
WHEN Sdept = '信息管理系' THEN 'IM'
END '所在系'
FROM Student

注意

  1. CASE和查询的列名之间 加一个 ',' 这一点容易会被忽略
  2. 每一个 WHEN语句之间不用 ',' 分割

2.CASE应用示例

示例1:查询“C04”号课程的考试情况,列出学号和成绩,同时对成绩进行如下处理
成绩大大于等于90,则在显示优
80~89:良
70~79:中
60~69:及格
60以下:不及格

SELECT Sno, Grade,
CASE
WHEN Grade >= 90 THEN '优'
WHEN Grade >= 80 AND Grade <= 89 THEN '良'
WHEN Grade >= 70 AND Grade <= 79 THEN '中'
WHEN Grade >= 60 AND Grade <= 69 THEN '及格'’
WHEN Grade < 60 THEN '不及格'
END 等级
FROM SC
WHERE Cno = 'C04'

示例2:统计 ‘计算机系’ 每个学生的选课门数,包括没有选课的学生。列出学号,选课门数和选课情况,其中选课处理情况为:
选课门数超过4门,则为多
选课门数2~4:一般
选课门数少于2:少
没有选课:未选

分析

  1. 涉及到学生的有选课和未选课,因此需要用的外链接
  2. 分情况处理,所以需要 CASE
SELECT S.Sno 学号, COUNT(Cno) 选课门数
CASE
WHEN COUNT(Cno) >= 4 THEN '多'
WHEN COUNT(Cno) >= 2 AND COUNT(Cno) < 4 THEN '一般'
WHEN COUNT(Cno) == 1 THEN '少'
WHEN COUNT(Cno) == 0 THEN '未选'
END 选课情况
FROM Student S LEFFT JOIN SC S.Sno=SC.Sno
WHERE Sdept = '计算机系'
GROUP BY S.Sno

为何用到外链接: 因为查询的要求是涉及到了学生表和课程表,所以需要利用到两张表的连接
为何是左外联而不是右外联: 因为查询的最终主体是学生,所以应该让学生全部显示出来而不是把课程全部显示出来。所以需要 左连学生表
为何使用GROUP BY: 因为统计的是 ‘计算机系’,所以需要对 ‘计算机系’ 进行分组统计

4.将查询结果保存到表中

之前的查询都是把数据保存在内存中的,构建的是一张临时表,如果需要持久化存储。SQLServer提供了 INTO语句,讲查询结果写入一个新表,新表就可以通过数据库实现永久化存储
示例1:讲"计算机系"学生的学号,姓名,性别,年龄,保存到新表 Student_CS中

SELECT Sno, Sname, Ssex, YEAR(GETDATE())-YEAR(Sbirthday) Sage
INTO Student_CS
FROM Student WHERE Sdept = '计算机系'

查询结果保存在新表中后就可以对新表进行查询即可得到结果

5.子查询

1.使用子查询进行基于集合的测试

示例1:查询与“钟文辉”在同一个系学习的学生学号,姓名,性别,所在系
使用子查询的方式我们可以拆开SQL语句

  1. 查找与“钟文辉”同系的所有系
  2. 再在这个系中查找这个集合中的所有学生信息

①查找与“钟文辉”同系的所有系

SELECT Sdept FROM Student WHERE Sname='钟文辉'

②再在这个系中查找这个集合中的所有学生信息

SELECT Sno, Sname, Ssex FROM Student
WHERE Sdept IN(xxx)

①和②合并就是:

SELECT Sno, Sname, Ssex FROM Student
WHERE Sdept IN(SELECT Sdept FROM Student WHERE Sname='钟文辉')

说明

SQL 语句是先执行子查询,然后再执行外层查询

2.使用子查询进行比较测试

子查询进行比较测试的语法格式为:

WHERE <列名> 比较运算符(子查询)

示例1:查询选了“C04”号课程且成绩高于此课程的平均成绩的学生的学号和该门课程成绩
分析:

  1. 查询选了“C04”号课程的平均成绩查找出来
  2. 然后步骤1中的结果作为条件进行查询选了“C04”,且成绩高于步骤1结果中的平均成绩的学号和成绩

①查询选了“C04”号课程的平均成绩查找出来

SELECT AVG(Grade) FROM SC WHERE Cno='C04'

②查询选了“C04”,且成绩高于步骤1结果中的平均成绩的学号和成绩

SELECT Sno, Grade
FROM SC
WHERE Cno = 'C04' AND Grade > (xxx)

①和②合并就是:

SELECT Sno, Grade
FROM SC
WHERE Cno = 'C04' AND Grade > (SELECT AVG(Grade) FROM SC WHERE Cno='C04')

3.使用子查询进行基于集合的测试

运算符 含义
> ANY 大于查询结果中的某个值
< ANY 小于查询结果中的某个值
>= ANY 大于等于查询结果中的某个值
<= ANY 小于等于查询结果中的某个值
= ANY 等于查询结果中的某个值
!= ANY 或<> ANY 不等于查询结果中的某个值
> ALL 大于查询结果中的所有值
< ALL 小于查询结果中的所有值
>= ALL 大于等于查询结果中的所有值
<= ALL 小于等于查询结果中的所有值
= ALL 等于查询结果中的所有值
!= ALL或<> ALL 不等于查询结果中的所有值

示例1:查询比“C03”课程成绩都高的选了“C04”课程的学生的学号和成绩

SELECT Sno, Grade FROM SC
WHERE Cno='C04' AND GRADE > ALL
(SELECT Grade FROM SC WHERE Cno='C03')

4.带EISTS谓词的子查询

EXISTS:相当于true
NOT EXISTS:相当于false
一般用于存在性测试
示例1:查询选了“C04”号课程的学生姓名

SELECT Sname FROM Student
WHERE EXISTS(
SELECT * FROM SC
WHERE SC.Sno=Student.Sno AND Cno = 'C04'
)

执行过程分析:

  1. 无条件执行外层查询语句,在外层查询的结果集中选取第一行结果,得到Sno的一个当前值,然后根据此Sno值处理内层查询
  2. 将外层Sno值作为结果,在内层查询中如果条件满足WHER子句,则为真,当前Sno满足查询结果;如果为假,则当前Sno不满足,读取外层循环的下一个Sno
  3. 循环处理表中第2,3,4…n行数据,直到外层数据查询完毕为止

总结:

  1. 带有 EXISTS的子查询是先执行外层查询然后再执行内层查询
  2. 由外层查询的值决定内层查询的结果,外层查询的结果决定内层查询的执行次数

6.查询的集合运算

UNION:并集
INTERSECT:交集
EXCEPT:差集
示例1:查询“计算机系”和“机电系”的所有学生信息

(SELECT Sno, Sname, Ssex, Sdept FROM Student WHERE Sdept='计算机系')
UNION
(SELECT Sno, Sname, Ssex, Sdept FROM Student WHERE Sdept='机电系')

示例2:查询同时选修了“C03”与“C04”课程的学生学号

(SELECT Sno FROM SC WHERE Cno='C03')
UNION
(SELECT Sno FROM SC WHERE Cno='C04')

示例3:查询选修了“C01”但没选“C02”课程的学生的学号

(SELECT Sno FROM SC WHERE Cno='C01')
EXCEPT
(SELECT Sno FROM SC WHERE Cno='C02')

2.视图

1.视图概述

  1. 视图是基于SQL语句的结果集的可视化的表。
  2. 与表不同的是它只存储视图的定义而不存储视图所包含的数据,这些数据人存放在原来的基本表中。

优点:

  1. 视图数据始终与基本表数据保持一致,视图仅存储了查询语句,所以每次视图的查询最终都会落实到基本表中的数据
  2. 节省存储空间

2.视图定义和使用

示例1:创建一个包涵“计算机系”学生的成绩单视图,视图中包含学生的学号,姓名,课程号,课程名和成绩信息

CREATE VIEW V_GRADE_CS
AS
SELECT S.Sno, Sname, C.Cno, Cname, Grade
FROM Student S, SC, Course C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno
AND Sdept = '计算机系'-- 查询视图
SELECT * FROM V_GRADE_CS

一般不建议通过视图来修改表数据

3.视图的修改与删除

示例1:将上个所得到的V_GRADE_CS视图加一个学生的年龄信息

ALTER VIEW V_GRADE_CS
AS
SELECT S.Sno, Sname, YEAR(GETDATE())-YEAR(Sbirthday) Sage, C.Cno, Cname, Grade
FROM Student S, SC, Course C
WHERE S.Sno=SC.Sno AND SC.Sno=C.Cno
AND Sdept ='计算机系'

示例2:删除上述中的视图

DROP VIEW V_GRADE_CS

注意

如果被删除的视图A是其他视图B的数据,那么删除视图A将会导致视图B无法使用;同样的基本表被删除后也会导致视图无法使用。

3.数据更改功能

1.数据的插入

单行插入示例1:向Student表中插入(050101, 赵林, 男, 1999-09-08, 计算机系)的纪录

INSERT INTO Student VALUES('050101', '赵林', '男', '1999-09-08', '计算机系', NULL)

多行插入示例2:用CREATE语句建立表StudentBAK,包含(与Student的Sno,Sname,Sdept相同)3个字段,然后向StudentBAK添加Studen表中的计算机系学生的学号,姓名,所在系的信息
1⃣️先创建StudentBAK表

CREATE TABLE StudentBAK(
Sno CHAR(6) PRIMARY KEY,
Sname NVARCHAR(20),
Sdept NVARCHAR(20),
)

2⃣️向StudentBAK表批量插入“计算机系”学生信息

INSERT INTO StudentBAK
SELECT Sno, Sname, Sdept FROM Student WHERE Sdept='计算机系'

2.数据更新

示例1:创建的Student_CS表中学生年龄加1

UPDATE Student_CS SET Sage=Sage+1

示例2:把“C04”课程学分加1

UPDATE Course SET Gredit = Gredit+1
WHERE Cno='C04'

基于其它表的更新。实例3:将数据库原理课程的成绩都减5分
1⃣️子查询实现

UPDATE SC SET Grade=Grade-5
WHERE Cno IN(SELECT Cno FROM Course WHERE Cname='数据库原理')

2⃣️多表链接实现

UPDATE SC SET Grade=Grade-5
FROM SC JOIN Course ON SC.Cno=Course.Cno

3.数据删除

示例1:删除Studetn_CS表中的数据

DELETE FROM Student_CS

实例2:删除数据库原理的选课记录
1⃣️子查询实现

DELETE FROM SC
WHERE Cno IN(SELECT Cno FROM COurse WHERE Cname='数据库原理')

2⃣️多表链接实现

DELETE FROM SC JOIN Course ON SC.Cno=Course.Cno
WHERE Cname='数据库原理'

4.数据控制功能

GRANT:授权
REVOKE:回收
DENY:拒权

1.授权

给用户May和John授权创建数据库和创建表的权限

GRANT CREATE DATABASE, CREATE TABLE
TO Mary, John

2.回收授权

将用户Mary和John创建数据库和创建表的权限回收

REVOKE CREATE DATABASE, CREATE TABLE
TO Mary, John

3.拒权

拒绝让Mary,John拥有CREATE DATABASE, CREATE TABLE全县,除非给他们显示授予权限

DENY CREATE DATABASE, CREATE TABLE
TO Mary, John

5.索引

1.概念

大家都知道索引可以提升数据库查询速度。
举例

假设我们在Student表的Sno列上建立了一个索引(Sno为索引项或索引关键字),则在索引部分就有指向每个学号所对应的学生的存储位置信息。【有点像数据结构中的“哈希表”:索引是按照数组顺序排列的,每个下标对应一个元素的信息】

当根据Sno查询Student上制定的学生信息的时候,它能够识别上该表上的索引列(Sno),并首先在索引部分(按学号有序存储)查找该学号,然后根据该学号指定的位置直接检索出要查询的信息。
如果没有索引,则需要从数据库第一行中一行一行比对的查找,我们都知道有列表的查找远高于无需表的查找

但索引带来高效率的同时也有着代价

  1. 索引在数据库中会占用一定的存储空间来存储索引信息
  2. 数据进行插入,更改和删除操作时为了使索引与数据保持一致,还需要对索引进行维护

2.存储结构及分类

索引分为两大类:一类是聚集索引;另一类是非聚集索引。它们都是由B树组结构实现
不熟悉树结构的朋友可以点击查看树的知识点

1.聚集索引

此B树是自下而上的建立。依靠索引值构造根节点,其索引关键字选取子节点最大或最小【构成大/小根堆】

对于频繁的修改茶如何删除,了解B树后肯定知道会破坏掉平衡性,但这些平衡性不需要用户或者程序员去关心,交给数据库管理系统自动调整,但这些调整过于频繁也会降低操作的性能
因此对于读取需求高的场景适合使用聚集索引,但对于频繁更改的列则不适合建立聚集索引

最后一点
在创建聚集索引之前先了解数据是如何被访问的,因为数据的访问方式直接影响到索引的使用。不恰当的索引可能会事半功倍,因此索引有时候也并非是越多越好

2.非聚集索引

非聚集索引与聚集索引一样用B树结构,但两者有两个重要差别:

  1. 数据不按非聚集索引关键字值得顺序排序和存储
  2. 非聚集索引的叶级节点不是存放数据的数据页

一句话概括非聚集索引
因此聚集索引的最后的数据页都是按照索引排好序的;非聚集索引则是无序的。非聚集索引的每个内容都可以找到单内容并不按照索引的顺序排列下来。

3.创建和删除索引

示例1:为Student表的Sname列创建非聚集解索引

CREATE INDEX Sname_ind
ON Student(Sname)

实例2:为Student表的Sid列创建唯一聚集索引

CREATE UNIQUE CLUSTERED INDEX Sid_ind
ON Student(Sid)

示例3:为Employee表的FirstName和LastName列创建一个聚集索引

CREATE CLUSTERED INDEX EName_ind
ON Employee(FIrstName, LastName)

示例4:删除Student表中的Sname_ind索引

DROP INDEX Student.Sname_ind

速学Sql Server从基础到进阶相关推荐

  1. SQL Server调优系列进阶篇(如何维护数据库索引)

    前言 上一篇我们研究了如何利用索引在数据库里面调优,简要的介绍了索引的原理,更重要的分析了如何选择索引以及索引的利弊项,有兴趣的可以点击查看. 本篇延续上一篇的内容,继续分析索引这块,侧重索引项的日常 ...

  2. c井语言和SQL第一章上机1,第一章 SQL Server 数据库基础复习内容(上机)

    上机课程总目标 在本学期中,将模拟开发一套学员信息管理系统,用来管理学员的个人基本资料,老师资料,学生成绩,课程信息等教学相关内容,以实现学校的信息自动化,提高工作效率. 该系统包括学生档案管理.学生 ...

  3. 1 SQL server数据库基础

    SQL server数据库基础 一 数据库简介 1数据库的基本概念 1)数据 ·描述事物的符号记录称为数据(Data),包括数字.文字.图像.声音等.以"记录"的形式按统一格式进行 ...

  4. [转]SQL Server 索引基础知识(2)----聚集索引,非聚集索引

    SQL Server 索引基础知识(2)----聚集索引,非聚集索引 [来自]http://blog.joycode.com/ghj/archive/2008/01/02/113291.aspx 由于 ...

  5. SQL Server 2008 基础

    SQL Server 2008 基础 SQL流程 TDS是一种协议,一系列描述两个计算机间如何传输数据的规则.象别的协议一样,它定义了传输信息的类型和他们传输的顺序.总之,协议描述了"线上的 ...

  6. SQL Server 索引基础知识(8)--- 数据基本格式补充(转自蝈蝈俊.net)

    我在SQL Server 索引基础知识系列中,第一篇就讲了记录数据的基本格式.那里主要讲解的是,数据库的最小读存单元:数据页.一个数据页是8K大小. 对于数据库来说,它不会每次有一个数据页变化后,就存 ...

  7. 学 SQL Server 我最常逛的 5 个网站

    点击蓝色"有关SQL"关注我哟 加个"星标",天天与10000人一起快乐成长 很多读者加我微信,问的问题都很类似,"有没有好的书可以推荐", ...

  8. SQL Server调优系列进阶篇(查询优化器的运行方式)

    前言 前面我们的几篇文章介绍了一系列关于运算符的基础介绍,以及各个运算符的优化方式和技巧.其中涵盖:查看执行计划的方式.几种数据集常用的连接方式.联合运算符方式.并行运算符等一系列的我们常见的运算符. ...

  9. sql server T-SQL 基础

    SQL语言按照用途可以分为如下3类: ①DDL(Data Definition Language)  数据定义语言: 定义修改和删除数据库.表.索引和视图等 ②DML(Data Manipulatio ...

  10. 数据库开发基本操作-SQL Server数据库基础知识

    数据库是一个信息系统应用程序的重要组成部分,在Web开发中,应用更加广泛,要学习好Web开发和ADO.NET,就必须对数据库有一定的了解. 数据库的概念很广,可以从很多方面进行解释.但是在计算机中,它 ...

最新文章

  1. 静态配置_【实验】华为静态路由基础配置
  2. 树状笔记软件for linux,Ubuntu 14.04安装开源树状笔记管理软件 WikidPad 2.2
  3. Mac系统Git生成ssh公钥
  4. vue 编译警告 Compiled with 4 warnings
  5. H5页面遮罩弹框下层还能滚动的问题
  6. WebVie打开woffice文档
  7. Python学习笔记:常用内建模块1
  8. 07丨行锁功过:怎么减少行锁对性能的影响
  9. sqlserver-事务处理
  10. 深度残差网络的无人机多目标识别
  11. OSPF——虚链路详解(含配置命令)
  12. Java多线程:线程停止
  13. 【ElasticSearch】Es 源码之 PersistentTasksExecutorRegistry 源码解读
  14. TopJui 我踩的那些坑
  15. 集成电路模拟版图入门-版图基础学习笔记(六)
  16. Flutter-防京东商城项目-修改收货地址 删除收货地址-43
  17. jQuery打字效果
  18. 深度强化学习中深度Q网络(Q-Learning+CNN)的讲解以及在Atari游戏中的实战(超详细 附源码)
  19. 在R中统计数据的频数或者密度分布并图形化
  20. python 英文语义分析_spinrewriter英文伪原创工具,Python对接API示例

热门文章

  1. Gradle 2.0 用户指南翻译——第六十三章. 比较构建
  2. iMeta观点 | 短读长扩增子测序是否适用于微生物组功能的预测?
  3. oracle中distance用法,distance的用法总结大全
  4. 解决谷歌浏览器最新chrome94版本CORS跨域问题(海康视频插件无法播放的问题)
  5. 中国平安会不会成为美国的世通或者安然?
  6. 优酷Android包瘦身治理思路
  7. Linux 上如何清除 RAM 内存高速缓存,缓存和交换空间
  8. x86 x64 IA64的关系和区别
  9. Java线程池工作原理
  10. 海伦公式c语言double,海伦公式