SQL 是向数据库表达查询和数据操作要求的语言;关系数据库把数据组织在表中,表用列描述属性、用行保存记录。MySQL 是能够执行 SQL 的数据库软件,客户端则负责把语句发过去、把结果显示出来。看懂一张学生表,就能把这些名称与具体对象对应起来。

从学生表辨认库、表、行和列

把学生信息放在名为 learning 的数据库中,其中一张表叫 students。数据库用于组织表等对象;“表”有自己的名称和列结构,用来保存某一类记录。一个库可以包含多张表,例如学生表与班级表分别保存不同对象的信息。

下面的 students 表有三条学生记录、三列属性:

student_id student_name class_name
1001 林晓 一班
1002 陈雨 二班
1003 周宁 一班

横着读编号为 1002 的这一行,得到的是陈雨这名学生的一条记录:学生编号是 1002,姓名是陈雨,所在班级是二班。这张表约定一行对应一个学生,三行就对应三名学生。判断“一行记录了什么”时,要看这一行各列合起来描述的对象;这里只有姓名、编号和所在班级,记录的对象是学生。

竖着看 student_name 这一列,读到的是林晓、陈雨、周宁三个姓名。同一列描述同一种属性,不同行提供这个属性各自的值。列名 student_name 是属性的名称,陈雨才是其中一个值;列标题单独列在表格顶端,不算第四条学生记录。表格横纵交叉的一格,例如编号 1002 那一行的 class_name 值“二班”,表示这名学生的一个属性值。

列还有数据类型,用来规定这一列按什么类型保存和处理值。例如姓名列可以使用文本类型,学生编号列可以使用整数类型。同一列中的值要遵守该列的类型规则,不能因为表格里都能显示文字,就认为每一列都可以随意混放各种内容。列名说明“这是什么属性”,类型说明“这类值怎样表示”,二者承担不同作用。

库与表是包含关系,行和列则共同构成表中的记录结构。图里的箭头表示库包含表,不表示查询的执行顺序:

Mermaid 图 1

students 是上面已有三条记录的表;classes 表示同一个库还可以容纳另一张班级表。学生表的一条记录可以写明学生属于哪个班级,班级表则保存班级本身的信息,两张表由班级信息建立关联。这也是关系数据库组织数据的一种常见方式:分别保存不同对象的记录,再按需要使用对象之间的关联。

在 MySQL 中,learning.students 表示 learning 库中的 students 表。句点前面是库名,后面是表名。读到这个名称,就能先确定数据属于哪个库、哪张表,再去辨认表里的行和列。

SQL 写要求,MySQL 执行,客户端收发

有了学生表,就可以提出一个具体要求:查看所有学生的编号、姓名和所在班级。写成 SQL,可以是下面这样;执行的前提是 MySQL(或者其他数据引擎)中已经存在具有上述三列和三条记录的 learning.students 表,并且当前连接具有相应查询权限。

SELECT 
  student_id, 
  student_name, 
  class_name
FROM learning.students;

SELECT 后面列出要查看的三个列名,FROM 后面指明数据来自哪张表。这条语句描述了“从哪里取、要哪些属性”;它没有新增学生,也没有修改姓名。按上面的表内容,返回的是三条学生记录,每条记录包含指定的三列。查询结果常被客户端显示成表格,表格的列标题来自所选列,标题下面才是返回的数据行。

SQL 的英文全称是 Structured Query Language,中文通常称为结构化查询语言。它除了查询,还能表达建表、新增、修改和删除数据等要求。MySQL 则是一套数据库管理系统:它管理库和表,并由服务器处理收到的语句。两者的关系是语言与执行这种语言的软件,名称中都有“SQL”并不代表它们是同一个对象。

客户端是人操作数据库时使用的入口,例如 mysql 命令行客户端。用户在客户端输入 SQL,客户端把语句提交给已经连接的 MySQL 服务器;服务器执行查询并返回结果,客户端再把结果显示给用户。这里的“服务器”指运行数据库服务的软件,它可以与客户端运行在同一台电脑上,也可以运行在另一台机器上。

把查询放进这个交互过程,SQL 文本、数据库软件与客户端就各有明确位置:

Mermaid 图 2

图中的 SQL 是客户端发给服务器的内容,MySQL 服务器是执行查询的一方。屏幕上看到的结果表格由客户端展示,表中保存的学生记录由数据库系统管理。换一个客户端,界面和按钮可能改变;语句要采用哪种数据库方言,主要看它连接的数据库产品。

同一个查询要求,方言写法可以不同

SQL 有通用概念和标准,不同数据库产品在具体语法上也有差异,这些差异通常称为 SQL 方言。MySQL 和 SQL Server 都能查询表,但同一个要求可能需要不同的关键字或关键字位置。以下 MySQL 示例以 8.4 为依据;SQL Server 的写法只用于对照。

沿用前面的三条学生记录,要求是“按学生编号从小到大排列,最多取两条”。MySQL使用 LIMIT 表达返回行数的上限:

SELECT student_id, student_name
FROM learning.students
ORDER BY student_id
LIMIT 2;

ORDER BY student_id 表示按学生编号升序排列,LIMIT 2 表示最多返回两行。对于编号分别为 1001、1002、1003 的三条记录,结果是林晓与陈雨两名学生的编号和姓名。这里写排序条件,是为了明确“取哪两条”;只限制行数而不指定排序,不能把偶然显示在前面的记录当成固定的前两名。

SQL Server 可以用 TOP (2) 表达相同的行数上限。假设它的当前数据库、默认架构下也存在同列同数据的 students 表,对照写法为:

SELECT TOP (2) student_id, student_name
FROM students
ORDER BY student_id;

这里的 TOP (2) 跟在 SELECT 后面,MySQL 的 LIMIT 2 则放在语句后部。两条查询在给定数据与排序条件下表达同一个要求,但不能把第二条当作 MySQL的语法直接执行。客户端即使允许输入这段文字,也不能据此判断服务器接受这种写法。

下图比较的是同一查询要求的两种表达:

Mermaid 图 3