SQL 语句快速复习

出于面试的需要,快速复习(虽然这么说,但我现在只会增删改查而已,复杂的查询早忘了,毕竟学过以后好久没再使用过)一下 SQL 的语法和。这里仅仅关注语法——数据库设计,调优等不是我现阶段(可能也包括将来)追求的目标,

这里使用 mariaDB 进行学习,使用 vscode 和 SQLTools 插件。很据《SQL 必知必会》第四版学习,表和数据使用作者在其网站中提供的 文件

基本概念

数据库 (database) 使用表 (table) 来存储数据。模式 (schema) 可以描述表的信息。表可以通过模式来 create,也可以直接给定各列来 create,这里可以联想类,对象和匿名实现类的关系。

表通过行列来存储数据。表由列 (column) 组成,每一列都代表部分信息。每一列都有自己的数据类型。数据是按行存储的。每个记录 (record) 为一行 (row)。

列也叫字段 (field)。

每一行都有一列(或多列)来唯一地标识自己。比如学生的学号,记录用户操作的用户名,时间戳(只有用户名,只有时间戳都不能唯一地确定一个操作,因为同一时间戳可以有多个用户操作,同一个用户可以有多个时间戳的操作,而同一个用户在同一个时间戳内只能执行一个操作)。这个(几)列称为主键 (primary key)。主键并非是强制要求的,但是其应当有。

主键满足以下要求——

  • 任何两个记录的主键不能重复。
  • 主键中每一列都不能为 NULL
  • 下面两个要求我测试了一下,可以啊……怪
  • 主键列的值不允许被更新
  • 主键值不能重用(被删除后,该主键无法赋给新行)

SQL 是 Structured Query Language(结构化查询语言)的缩写。它负责与数据库(或许更准确的来说,是 DBMS,Database Management System 数据库管理系统)沟通。

结构化的语言可以认为是用呈一定结构的自然语言来进行编程的语言,如 C#的 LINQ,Common Lisp 的 Loop 宏,其也都是一种结构化语言。

SELECT——检索数据

SQL 使用–进行单行注释,使用 C 风格的/**/进行多行注释。

SELECT语句从一个或多个表中检索信息。

1
2
3
4
5
6
7
8
-- 检索一列
SELECT prod_name FROM Products; -- 这将返回所有行的 prod_name。

-- 检索多列
SELECT prod_id, prod_name, prod_price
FROM Products;
-- 检索所有 (实际上查询了整个表)
SELECT * FROM Products;

DISTINCT——保证检索值唯一

SELECT可以使用DISTINCT子句来约束,保证每一行都是唯一的(也就是说过滤掉完全重复的行)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT vend_id FROM Products;
/*
BRS01
DLL01
FNG01
FNG01
*/
SELECT DISTINCT vend_id
FROM Products;
/*
BRS01
DLL01
FNG01
*/

LIMIT——限制结果数量

SELECT语句返回匹配的行——可能是所有,也可能是前 1000 行或其他数字。使用LIMIT子句可以限制最多返回多少行。LIMIT可以和OFFSET搭配使用,表示从某一行开始返回。OFFSET零索引的。所以LIMIT iLIMIT i OFFSET 0同义。

1
2
3
4
5
6
7
SELECT prod_name
FROM Products
LIMIT 5; -- 这是 MySQL 和 MariaDB 的语法,其它 SQL 语法不一样。

SELECT DISTINCT prod_name -- 关键字可以联合使用
FROM Products
LIMIT 5 OFFSET 5; -- 从第 5 行开始检索。

ORDER BY——排序结果

应该假定,如果不明确进行排序,则检索到的数据的顺序是无意义的

ORDER BY子句让各记录根据其一个列或多个列的值来排序。使用ASC(升序排序,它是默认的)和DESC(降序)关键字来规定升序还是降序排序。要降序排序的每一列都需要明确给定DESC

需要注意的是,ASC/DESC需要给在列名后面…就像副词的用法。

DESC 是 DESCENDING 的缩写,ASC 是 ASCENDING 的缩写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT prod_name
FROM Products
ORDER BY prod_name; -- 根据名字排序

SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price, prod_name;-- 先按 price 排序,如果 price 相等,按 name 排序。

SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY 2, 3; -- 也可以根据列位置来排序,比如这里的 2 代表 price,3 代表 name。这样的缺点是如果列位置改变,数字也需要改变,而且如果排序的根据不在结果列里(比如我想根据 desc 进行排序,虽然我不要这个数据),则无法这样使用。

SELECT DISTINCT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price DESC, prod_name, prod_desc DESC; -- 先根据 price 降序排列,如果 price 相等,再根据 name 升序排列,如果 name 相等,则根据 desc 降序排列。

WHERE——过滤数据

WHERE子句如此重要,以至于要给它一个 h1 标题 XD。

检索所有行的情况是很少的,通常需要依据一定的需要提取表数据的一个子集。

只检索所需数据,需要指定搜索条件 (search criteria), 其也称为过滤条件 (filter condition).WHERE就是提供这样功能的子句。

WHERE提供很多操作符,如=, <>(!=), < ,<= ,>, >=, !<(不小于), !>(不大于), BETWEEN (它接受a AND b这样的形式的第二个参数), IS NULL

1
2
3
4
5
6
7
8
9
SELECT prod_name, prod_price
FROM Products
WHERE prod_price = 3.49
ORDER BY prod_name DESC;

SELECT prod_name, prod_price
FROM Products
WHERE prod_price BETWEEN 3 AND 5
ORDER BY prod_name DESC;

同时使用ORDER BYWHERE时,ORDER BY应当放到WHERE后。

AND & OR

其还可用ORAND来连接多个条件。AND子句优先级更高。可以使用括号来决定运算顺序。(事实上,除了加减乘除,其他任何包括不同优先级运算符的表达式都应该强制使用括号来规定运算顺序。)

1
2
3
4
5
6
SELECT prod_name, prod_price
FROM Products
WHERE prod_price = 3.49
AND prod_name != "ignored"
OR prod_desc IS NULL
ORDER BY prod_name DESC;

IN——在……之中

IN子句用途是枚举条件的可选范围。它接受一对原括号扩起来的,用逗号分割的一组合法值。它也可以包含其他 SELECT 语句,但是该 select 要求返回只有一列的表,比如SELECT id from user;

顺带一提,一行一列的表同字面量(如字符串,数字之类的东西)是一样的效果。比如这样一个没有实际意义且性能低下但可供演示的例子——SELECT * FROM place WHERE place_name = (SELECT place_name FROM place WHERE place_name="北京" LIMIT 1)

1
2
3
4
SELECT  prod_name, prod_price
FROM Products
WHERE vend_id IN ("DLL01", "BRS01") -- 等同于 vend_id = "DLL01" OR vend_id = "BRS01"
ORDER BY prod_name;

NOT

NOT顾名思义,对结果取非。注意其位置,它放在每一个条件前。

1
2
3
4
5
SELECT  prod_name, prod_price
FROM Products
WHERE NOT vend_id IN ("DLL01", "BRS01") -- 有趣的是,这里的 NOT 也可以放到 IN 的前面
AND NOT prod_name = "King doll"
ORDER BY prod_name;

通配符

所谓通配符,就是根据值的一部分来进行匹配的特殊字符。通配符和字面值组合成为的搜索条件称为搜索模式(search pattern)。显然,通配符只能用来匹配字符串。

LIKE 操作符

此书说技术上来说 LIKE 不是操作符……先放着。

LIKE是一个谓词(predicate……不得不联想到 Lisp 里的谓词)用来判断字符串是否匹配该搜索条件。一般说“用LIKE进行通配搜索”。

%通配符

%通配符用来匹配任何字符出现任意次数(就如同 regex 的。*吗?)。

比如下面的搜索模式检查 name 是否以 Fish 开头。

1
2
SELECT prod_name FROM Products
WHERE prod_name LIKE "Fish%";

%可以匹配 0 个或任意多个字符,但是 NULL 不行,LIKE “%”不能匹配 NULL。

一个需要注意的地方是,许多 DBMS 会用空格来填充未使用的地方,比如假设某列有 50 个字符,只用了 10 个字符,其后 40 个字符会被填充为空格,这有时候会对通配搜索产生影响。

_通配符

_通配符匹配且只匹配一个字符,Over。

[] 通配符

[]通配符用法就如 regex 中的[]。mariaDB 不支持集合通配符,所以 pass。


时代变啦,本来是为找工作学习 SQL,现在已经找到了。但是还是得继续学习。争取将来忘记了啥语法之类的时候只看这篇文章就够了。 顺便,现在改用 Mysql……毕竟这玩意是最常用的(而且懒得装新的数据库了)

计算字段

最近专注毕设,毕业之前估计是不会再去主动学了。等工作时接触再继续吧。——2021.05.04