《SQL必知必会》学习笔记

说明:《SQL必知必会》这本书的学习过程做一个记录,便于以后的查阅和复习;本文持续更新,最后更新时间为2019-10-05

第一课 了解SQL

数据库基础

数据库

一个以某种有组织的方式存储的数据集合,或者说是保存有组织的数据的容器。

某种特定类型数据的结构化清单,不同的数据应存储在不同的表中。同一个数据库中的表应具有唯一的名字。
模式是指关于数据库和表的布局以及特性的信息。这些信息定义了数据在表中如何存储、存储什么样的数据、数据如何分解等。

列和数据类型

是表中的一个字段,表是由一个或多个列组成的,表中的每一列存储着某种特定的信息。
数据类型限制该列存储的数据,每一列都有相应的数据类型。

数据需要正确的被分解为多个列,这是极为重要的!

表中的数据是按行存储的,一行是表中的一个记录。

主键

是一列(或一组列),其值能够唯一的标识表中的每一行。任何列都可以作为主键,需满足以下条件

1.任意两行的主键值不同
2.主键值不能为空
3.主键列的值不允许修改或更新
4.主键值不能重用(如果某行被删除,它的主键不能赋给以后的新行)

如果使用多列作为主键,则这些列都必须满足上述条件。列的组合必须唯一,单个列的值可以不唯一。

第二课 检索数据

SELECT语句

SELECT语句用于从表中检索一个或多个数据列。SELECT这样的是关键字,是作为SQL组成部分的保留字,不能用作表或列的名字。

检索单个列

SELECT 列名 FROM 表名;

使用以上语句从某一表中检索其中的一列。

检索的数据没有特定的顺序

SQL语句不区分大小写,一般关键字使用大写以增强可读性;每一条SQL语句以分号;结尾,空格可忽略且可以分写在多行。

检索多个列

SELECT 列名1,列名2,...,列名n FROM 表名;

检索多个列,列名间使用逗号,分隔,最后一个列名后无需逗号。

检索的数据以原始、无格式输出

检索所有列

SELECT * FROM 表名;

使用通配符*可以检索所有列,能够检索出名字未知的列;但是检索所有列可能会降低检索和应用程序的性能。

检索不同的值

当一列中存在重复的值,而又不希望每次都出现,可以使用DISTINCT关键字。

SELECT DISTINCT 列名 FROM 表名;

不能部分使用DISTINCT,该关键字作用于后面跟的所有列,若后续的列不完全相同也会被检索出来

限制结果

只输出一定数量的行采用以下方式

SELECT TOP n 列名 FROM 表名;  --检索前n行(SQL Server、Access)

SELECT 列名 FROM 表名 FETCH FIRST n ROWS ONLY;  --检索前n行(DB2)

SELECT 列名 FROM 表名 WHERE ROWNUM <=n;  --检索前n行(Oracle)

SELECT 列名 FROM 表名 LIMIT n;  --检索前n行(MySQL、MariaDB、PostgreSQL、SQLite)

如果需要检索特定行开始的n行数据使用以下方式

SELECT 列名 FROM 表名 LIMIT n OFFSET m;  --检索从m行开始的n行

SELECT 列名 FROM 表名 LIMIT m,n;  --MySQL、MariaDB、SQLite的简化语法

首行是第0行而非第1行

使用注释

# 这是一条注释(该形式很少得到支持)
SELECT 列名 FROM 表名;  --这是一条注释
/*SELECT 列名
FROM 表名;*/

第三课 排序检索数据

排序数据

如果不明确规定排序顺序,则不应该假定检索出的数据的顺序有任何意义

SQL语句由子句构成,有些是必需的;子句通常由一个关键字加上所提供的数据组成。
使用ORDER BY子句取一个或多个列,对输出进行排序。

SELECT 列名 FROM 表名 ORDER BY 列名;

ORDER BY子句必须是SELECT语句中的最后一条子句,否则会报错

按多个列排序

要按多个列进行排序,指定列名,列名间用,分隔

SELECT 列名1,列名2,...,列名n FROM 表名 ORDER BY 列名1,列名2,...,列名m;

按多个列排序时按照列名在语句中的顺序依次进行,即先按列1进行排序,然后再按列2进行排序...

只有当多个行在要进行排序的列下具有相同的值时才会按照后面的列进行排序

按列位置排序

SELECT 列名1,列名2,...,列名n FROM 表名 ORDER BY a,b,...;    --a,b,...为数值

a,b,...为需要进行排序的列在SELECT清单中列的相对位置

在使用这种方式时必须严格关注列的顺序

指定排序方向

默认排序方向是升序排序(A->Z),为了降序排序(Z->A),使用DESC关键字

SELECT 列名1,列名2,...,列名n FROM 表名 ORDER BY 列名 DESC;
SELECT 列名1,列名2,...,列名n FROM 表名 ORDER BY 列名1 DESC,列名2;   --先对列1降序排序,再对列2升序排序

DESC只对直接位于其前面的列有效,如果需要对多个列降序排序,则在每个列名后都需要添加DESC关键字

第四课 过滤数据

使用WHERE子句

SELECT语句中,数据根据WHERE子句中指定的搜索条件进行过滤。WHERE子句在表名(FROM子句)之后给出

SELECT 列名 FROM 表名 WHERE 条件;

在同时使用ORDER BYWHERE子句时,应使ORDER BY位于WHERE后,否则会报错。
数据也可以在应用程序中过滤,检索超出实际需要的数据然后由应用程序提取需要的内容,不过这种做法十分不妥

WHERE子句操作符

WHERE子句支持下面所列的所有条件操作符(部分操作符冗余,并非所有DBMS都支持这些操作符)。

操作符 说明 操作符 说明
= 等于 > 大于
<> 不等于 >= 大于等于
!= 不等于 !> 不大于
< 小于 BETWEEN 在指定的两个值之间
<= 小于等于 IS NULL 为NULL值
!< 不小于

在限定条件中,与字符串类型的列进行比较的值需要使用单引号

范围值检查

检查某个范围内的值可以使用BETWEEN操作符,其语法与其他WHERE子句的操作符稍有不同。

SELECT 列名 FROM 表名 WHERE 条件 BETWEEN m AND n;

其中m为范围的开始值,n为范围的结束值,两者使用AND关键字分隔。匹配结果是一个[m, n]的闭区间,结果中包含mn的匹配结果。

空值检查

创建表时可以指定其中的列能否不包含值,当不包含值时称为空值NULL。确定值是否为NULL不能检查是否= NULL,应使用IS NULL

SELECT 列名 FROM 表名 WHERE 条件 IS NULL;

NULL是没有值,与0、空字符串、仅包含空格不同。
匹配过滤或者非匹配过滤的时候不会返回含NULL值的行

第五课 高级数据过滤

组合WHERE子句

第四课中的WHERE子句都是单一条件,为了更强的过滤控制,SQL允许给出多个WHERE子句。有两种使用方式,以ANDOR子句方式使用。

AND操作符

要通过不止一个列进行过滤,可以使用AND操作符给WHERE子句附加条件。返回的结果同时满足条件1条件2

SELECT 列名 FROM 表名 WHERE 条件1 AND 条件2;

只包含一个AND则最多有两个过滤条件,多个条件则每个条件之间都要使用AND

添加的ORDER BY子句应位于WHERE子句之后

OR操作符

OR操作符与AND相反,它表示检索匹配任一条件的行。事实上,很多DBMS在满足第一个条件的情况下,不再计算是否满足第二个条件,相应的行都将被检索出来。

SELECT 列名 FROM 表名 WHERE 条件1 OR 条件2;

求值顺序

WHERE子句可以包含任意数目的ANDOR操作符,允许两者结合以进行复杂、高级的过滤。然而,组合使用时会优先处理AND操作符从而导致检索出不符合预期的结果,因此需要使用圆括号对操作符进行分组(也建议一直这么做)

IN操作符

IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。IN取一组由逗号分隔、在圆括号中的合法值。

SELECT 列名 FROM 表名 WHERE 列名 IN (条件1, 条件2, ...);

其功能与OR相当,表示检索出某一列满足任一条件的行,等价于

SELECT 列名 FROM 表名 WHERE 列名=条件1 OR 列名=条件2 OR ...;

使用IN操作符具有以下优点

1.在有很多合法选项时,更加清楚直观
2.在与ANDOR组合使用IN时,求值顺序更加容易管理
3.IN操作符比OR执行更快
4.可以包含其他SELECT语句,更动态的建立WHERE子句

NOT操作符

NOT操作符用于否定其后所跟的任何条件,并且总是与其他操作符一起使用。

SELECT 列名 FROM 表名 WHERE NOT 条件;

检索结果为不满足条件的所有行,也可以使用<>操作符完成。在复杂的子句中,如与IN联合使用时,可以非常简单的找出与条件列表不匹配的行。

MariaDB支持使用NOT否定INBETWEENEXISTS子句,绝大多数DBMS允许使用NOT否定任何条件

Last modification:October 5th, 2019 at 02:40 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment