SQL笔记
本笔记是根据SQL基础教程(MICK第2版)的学习笔记。粗略的记录了该书第二章到第七章的基础内容。后续会继续更新。
DDL(Database Definition Language,数据定义语言)
数据库和表的创建
创建数据库:CREATE DATABASE 数据库名称
表的创建 :CREATE TABLE 表名
表内容的创建:
CREATE TABLE 表名
(列名1 <数据类型> <该列所需约束>,
列名2 <数据类型> <该列所需约束>,
列名3 <数据类型> <该列所需约束>,
... ...
<该表约束1>,<该表约束2>,... ...)
约束:NOT NULL 约束; 表的主键约束(PRIMARY KEY(列名))等。
表的删除和更新
删除表(无法恢复):DROP TABLE 表名
添加列:ALTER TABLE <表名> ADD COLUMN <列的定义(包括数据类型和约束)>
删除列:ALTER TABLE <表名> DROP COLUMN <列名>
变更表名:RENAME TABLE <旧表名> TO <新表名>
DML(Database Manipulation Language,数据操纵语言)
列的查询
基本SELECT语句:SELECT <列名>,... ... FROM <表名>; 查询某列数据;当要查询所有列时,用 * 代表全部列。
设定别名(可以是中文,需要双引号""):
SELECT <列名> AS <别名>,
... ...
FROM <表名>
书写常数:
SELECT <字符串常数> AS <列名>,
<数字常数> AS <列名>,
<日期常数> AS <列名>
FROM <表名>
如下图 string、number、date:
删除重复行:在 SELECT 中使用 DISTINCT 实现。
SELECT DISTINCT <列1>,
<列2>,
... ...
FROM <表名>
注意:NULL也会作为一类数据,会合并该列其它 NULL 的数据。
WHERE语句:通过WHERE 子句来指定查询数据的条件。执行顺序:先通过 WHERE 子句查询出符合指定条件的记录,再选取出 SELECT 语句指定的列。
SELECT <列名>,... ...
FROM <表名>
WHERE (条件表达式);
注释:单行注释 -- 、多行注释 /* */ .
运算符
+、-、*、/ 称为算术运算符。SELECT <列名>,... ... , <运算操作> FROM <表名>
1、可以用括号提升运算表达式的优先级;
2、所有包含 NULL 的计算,结果肯定是 NULL。
比较运算符
注意:
-
1、对字符串使用比较运算符时的注意事项: 比较的是字典排序顺序。
- 2、不能对NULL使用比较运算符
逻辑运算符
NOT:对条件取反。AND:“并且”的意思。在其两侧的查询条件都成立时,整个查询条件才成立。OR:“或者”的意思。在其两侧的查询条件任意一个成立时,整个查询条件就成立。
MYSQL使用的是——三值逻辑TRUE、FALSE、UNKNOWN(不确定)
聚合与排序
聚合函数
常用的5个函数:
- 通常,聚合函数会对
NULL以外的对象进行汇总。 -
COUNT( * )会得到包含 NULL 的数据行数,而COUNT(<列名>)会得到NULL之外的数据行数。 -
MAX/MIN函数几乎适用于所有数据类型的列。SUM/AVG函数只适用于数值类型的列。 - 在聚合函数的参数中使用
DISTINCT,可以去掉重复数据。
分组
- 聚合键中包含NULL时,在结果中会以“不确定”行(空行)的形式表现出来。
- 使用聚合函数和GROUP BY子句时需要注意以下4点。
① 只能写在SELECT子句之中
② GROUP BY子句中不能使用SELECT子句中列的别名
③ GROUP BY子句的聚合结果是无序的
④ WHERE子句中不能使用聚合函数
常见问题
- 使用
GROUP BY子句时,SELECT子句中不能出现聚合键之外的列名。 - 在
GROUP BY子句中不能使用SELECT子句中定义的别名。 -
GROUP BY子句显示的结果是无序的。 - 只有
SELECT子句和HAVING子句(以及ORDER BY子句)中能够使用聚合函数。
为聚合结果指定条件
HAVING:对聚合函数结果指定条件。构成要素:常数,聚合函数,GROUP BY 子句中指定列名(聚合键)。
SELECT <列名1>, ... ...
FROM <TABLE>
GROUP BY <列名1>, ... ...
HAVING <分组结果对应的条件>
例子:可以在 HAVING 后使用SELECT 中的别名。
注意
- WHERE 子句 = 指定行所对应的条件
- HAVING 子句 = 指定组所对应的条件
- 在 WHERE 子句和HAVING 子句中都可以使用的条件,最好写在WHERE子句中。(因为可以减少排序行数和创建索引,以提高性能。)
排序
数据库查询的排列顺序是随机的。ORDER BY:对列进行排序(默认是升序ASC ),如需降序排序用关键字DESC。
- 在
ORDER BY子句中可以使用SELECT子句中定义的别名。 -
ORDER BY子句中可以使用SELECT中的列,也可以使用存在于表中、但并不包含在 SELECT 子句之中的列。 - 在
ORDER BY子句中可以使用SELECT子句中未使用的列和聚合函数。 - 在
ORDER BY子句中不要使用列编号。
各语句的书写排序:
各语句的执行顺序:
数据的更新
插入语句
INSERT INTO <表名> (列1, 列2, 列3, ……)
VALUES (值1, 值2, 值3, ……);
其中 (列1, 列2, 列3, ……)称为列清单,(值1, 值2, 值3, ……)称为值清单。插入数据时,两个的列数要保持一致,否则会报错。
- 原则上,执行一次INSERT语句应插入一行数据。
列清单的省略
对表进行全列 INSERT 时,可以省略表名后的列清单。这时 VALUES 子句的值会默认按照从左到右的顺序赋给每一列。
插入默认值
显式方法:用 DEFAULT 代替值。
隐式方法:在列清单和值清单中省略该列。
- 省略
INSERT语句中的列名,就会自动设定为该列的默认值(没有默认值时会设定 为NULL)。
从其他表中复制数据
插入查询得到的数据:
INSERT INTO <表1> (<列1><列2>, ... ...)
SELECT <列1>,<列2>, ... ...
FROM <表2>
-
INSERT语句的SELECT语句中,可以使用WHERE子句或者GROUP BY子句等任何SQL语法(但使用ORDER BY子句并不会产生任何效果)。
删除数据
①DROP TABLE 语句可以将表完全删除 ;
②DELETE 语句会留下表(容器),而删除表中的全部数据。
语法一:DELETE FROM <表名> 和 DELETE FROM <表名> WHERE
- DELETE语句的删除对象并不是表或者列,而是记录(行)。
- 可以通过
WHERE子句指定对象条件来删除部分数据。 - 与
SELECT语句不同的是,DELETE语句中不能使用GROUP BY、HAVING和ORDER BY三类子句.
语法二: TRUNCATE <表名>
- 只能删除表中全部数据,不能使用
WHERE。 - 可以缩短执行时间。
更新数据
UPDATE <表名>
SET <列名> = <表达式>;
:将列中的所有值更新为新的值。——会将列中 NULL 值更新为新值。
指定条件的 UPDATE 语句:
UPDATE <表名>
SET <列名> = <表达式>
WHERE <条件>;
- 使用
UPDATE语句可以将值清空为NULL(但只限于未设置NOT NULL约束的列)。
多列更新
- 需要注意的是第一种方法——使用逗号将列进行分隔排列,这一方法在所有的DBMS 中都可以使用。但是第二种方法——将列清单化(元组),这一方法在某些 DBMS中是无法使用的。
事务
事务是对表中数据进行更新的单位。简单来讲,事务就是需要在同一个处理单元中执行的一系列更新处理的集合。
创建事务
事务开始语句;
DML语句1;
DML语句2;
DML语句3;
事务结束语句(COMMIT或者ROLLBACK);
- 事务的开始语句:
-
COMMIT是提交事务包含的全部更新处理的结束指令,相当于文件处理中的覆盖保存。一旦提交,就无法恢复到事务开始前的状态了。 -
ROLLBACK是取消事务包含的全部更新处理的结束指令,数据库会恢复到事务开始之前的状态.
ACID特性
- 原子性(Atomicity):指在事务结束时,其中所包含的更新处理要么全部执行,要
么完全不执行。 - 一致性(Consistency):一致性指的是事务中包含的处理要满足数据库提前设置的约束,如主键约束或者 NOT NULL 约束等。
- 隔离性(Isolation):隔离性指的是保证不同事务之间互不干扰的特性。
- 持久性(Durability):持久性也可以称为耐久性,指的是在事务(不论是提交还是回滚)结束后,DBMS 能够保证该时间点的数据状态会被保存的特性——日志。
复杂查询
视图
表中存储的是实际数据,而视图中保存的是从表中取出数据所使用的SELECT语句。
优点:
- 视图无需保存数据,可以节省存储设备的容量。
- 可以将频繁使用的
SELECT语句保存成视图,就不用每次都重新书写SELECT语句。
创建视图:
# SELECT 中列与视图列要一一对应
CREATE VIEW 视图名称(<视图列名1>, <视图列名2>, ……)
AS
<SELECT 语句>
注意:可以使用多重视图,但应该避免在视图的基础上创建视图。
限制:
- 定义视图时不能使用ORDER BY 子句。(PostgreSQL例外)
- 如果定义视图的 SELECT 语句能够满足某些条件,那这个视图就可以被更新。具有代表性的条件有:① SELECT 子句中未使用 DISTINCT ② FROM 子句中只有一张表 ③ 未使用 GROUP BY 子句 ④ 未使用 HAVING 子句。
(视图和表需要同时进行更新,因此通过汇总得到的视图无法进行更新。)
删除视图:
DROP VIEW 视图名称(<视图列名1>, <视图列名2>, ……)
子查询
子查询是一次性视图(SELECT语句)。与视图不同,子查询在`SELECT`语句执行完毕之后会消失。
使用方法 :将用来定义视图的 SELECT语句直接用于 FROM 子句当中。
SELECT 的嵌套结构(先内再外)。
可以使用嵌套结构添加子查询层数。(但是,随着子查询嵌套层数的增加,SQL 语句会变得越来越难读懂, 性能会越来越差。)
标量子查询
标量子查询就是返回单一值的子查询。
使用地方: 能够使用常数或者列名的 地方,无论是 SELECT 子句、GROUP BY 子句、HAVING 子句,还是 ORDER BY 子句,几乎所有的地方都可以使用。
注意事项
- 该标量子查询绝对不能返回多行结果。
关联子查询:在细分的组内进行比较时,需要使用关联子查询。
- 关联子查询会在细分的组内进行比较时使用。
- 关联子查询和
GROUP BY子句一样,也可以对表中的数据进行切分。 - 关联子查询的结合条件如果未出现在子查询之中就会发生错误。
函数、谓词、CASE表达式
函数
新数据类型:NUMERIC (全体位数,小数位)
算术函数ABS(数值) :绝对值MOD(被除数,除数):求余数ROUND (对象数,小数保留位数) :保留小数位
字符串函数
拼接函数: MYSQL:CONCAT ( )、 SQL Server:+ 、 其它:||LENGTH (字符串):字符串长度LOWER (字符串):英文大写转小写UPPER (字符串):英文小写转大写REPLACE (字符串对象,替换前字符,替换字符):替换字符中某字符(三者中有一NULL就无法替换)。SUBSTRING (对象字符串 FROM 截取的起始位置 FOR 截取的字符数):截取字符串
日期函数CURRENT_DATE:获取当前日期(无时间)[SQL Server]CURRENT_TIME:获取当前时间 [SQL Server]CURRENT_TIMESTAMP:获取当前日期和时间EXTRACT(日期元素 FROM 日期):截取日期元素,即年、月、时、分(返回数值类型)[SQL Server]
转换函数CAST(转换前的值 AS 想要转换的数据类型):转换某个值的数据类型COALESCE(数据1,数据 2,数据 3……):将 NULL 转换成其它值
谓词: 谓词是需要满足返回值是真值的函数。LIKE :字符串的部分一致查询(%(n个任意字符)、( _ 任意一个字符));BETWEEN :范围查询(包含临界值)IS NULL、IS NOT NULL :判断是否为NULLIN 、 NOT IN :简化多个 OR 的谓词
- 在使用 IN 和NOT IN 时是无法选取出 NULL 数据。
- 能够将表和视图作为 IN 的参数。
- 可以使用子查询作为参数
EXISTS 、NOT EXISTS:“判断是否存在满足某种条件的记录 - 通常指定关联子查询作为EXIST的参数。
- 作为EXIST参数的子查询中经常会使用
SELECT *。
CASE表达式
什么是CASE表达式
(条件)分支函数。可以分为简单CASE表达式和搜索CASE表达式(包含了简单表达式的所有功能)。
搜索表达式:
CASE WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
... ...
ELSE <表达式>
END
可以使用 CASE 表示式实现行列转换:
简单表达式:简化书写,对CASE表达式求值,再对该值进行筛选
CASE <表达式>
WHEN <表达式> THEN <表达式>
WHEN <表达式> THEN <表达式>
WHEN <表达式> THEN <表达式>
... ...
ELSE <表达式>
END
集合运算
集合运算,是对满足同一规则的记录进行的加减等四则运算。
表的加减法(增减行数)
UNION(并集) :进行记录加法运算的集合运算符。UNION 后面添加 ALL 选项,可以包含重复行的集合运算。
UNION 等集合运算符通常都会除去重复的记录。
注意事项
- 作为运算对象的记录的列数必须相同
- 作为运算对象的记录中列的类型必须一致
- 可以使用任何SELECT语句,但ORDER BY子句只能在最后使用一次
INTERSECT(交集) :选取两个记录集合中公共部分。[ MYSQL ]
EXCEPT(差集) :进行减法运算的集合运算符。[ MYSQL ]
联结(添加列)
- 1、两个表中都包含的列
- 2、只存在于一张表内的列
- 3、将该表的列添加到另一张表
内联结INNER JOIN:内联结。只能选取出同时存在于两张表中的数据。
SELECT <表别名 . 列名> ... ...
FROM <表1> INNER JOIN <表2>
ON <联结条件>
WHERE ...
内联结要点
- 需要在FROM子句中使用多张表;
- 进行内联结时必须使用
ON子句,并且要书写在FROM和WHERE之间。 - 使用联结时
SELECT子句中的列需要按照<表的别名>.<列名>的格式进行书写。
外联结RIGHT/LEFT OUTER JOIN:结果中包含原表中不存在(在原表之外)的信息。
SELECT <表别名 . 列名> ... ...
FROM <表1> RIGHT OUTER JOIN <表2>
ON <联结条件>
WHERE ...
外联结要点
- 只要数据存在于某一张表当中,就能够读取出来
- 指定主表的关键字是
LEFT和RIGHT