SQL从入门到出门 第3篇 初级查询

时间:2022-06-11 20:01:22

本篇介绍SQL:2016(ISO/IEC 9075:2016)标准中定义的查询语句,以及六种主流数据库中的实现及差异:Oracle、MySQL、Microsoft SQL Server、PostgreSQL、Db2、SQLite。

从本篇开始,我们使用的示例数据库结构如下图所示。
SQL从入门到出门 第3篇 初级查询
其中包含7个表和1个视图。

  • regions,全球区域表
  • countries,国家信息表,通过region_id关联regions表
  • locations,街道地址表,通过country_id关联countries表
  • departments,部门信息表,通过location_id关联locations表,通过manager_id关联employees表
  • employees,员工信息表,通过department_id关联departments表,通过job_id关联jobs表,通过manager_id与自己关联
  • jobs,职位信息表
  • job_history,员工任职历史表,通过employee_id关联employees表,通过department_id关联departments表,通过job_id关联jobs表
  • emp_details_view,员工详细信息视图,同时显示了多个表中的关联信息

创建示例数据库的SQLite脚本点击下载

不同的数据库产品都提供了自己的管理和开发工具,例如MySQL的MySQL Workbench,Oracle的SQL Developer。本文推荐一个第三方的免费工具:DBeaver,它可以通过JDBC连接几乎所有的数据库。

先从最简单的查询开始,SQL中的查询使用SELECT语句表示。

最简单的查询

一个最简单的查询示例如下:

SELECT first_name, last_name FROM employees;

其中SELECTFROM称为关键字,它们不区分大小写,建议大写,便于阅读。

SELECT表示一条查询语句,后面是要显示的信息,使用逗号分隔;FROM表示要从哪个表中进行查询;分号表示语句结束。

更一般的查询语法如下:

SELECT column1, column2, ... 
  FROM table;

以上示例查询的结果如下(共计107条):
SQL从入门到出门 第3篇 初级查询

如果表中的列较多,为了快速查看所有列的信息,可以使用星号(*)表示。

SELECT * FROM employees;

以上查询将会显示employees表的所有列。
SQL从入门到出门 第3篇 初级查询

在实际项目中,不要使用 SELECT *,避免表结构变更带来的不确定性。

除此之外,许多数据库还支持另一种更简单的查询:

SELECT 1+1;

这种形式不属于SQL标准规范,它不需要FROM关键字,可以用于快速查询信息,或者当作计算器使用。

数据库 不带FROM的SELECT 描述
Oracle N/A                               Oracle提供了一个单行单列的dual表,用于执行这种简单的查询和计算:
SELECT 1+1 FROM dual;
MySQL OK MySQL也提供了dual表
SQL Server OK
PostgreSQL OK
Db2 N/A Db2也提供了Oracle中类似的表:
SELECT 1+1 FROM sysibm.sysdummy1;
SQLite OK

消除重复值

在SQL中,提供了DISTINCT关键字,用于删除查询结果中的重复值。例如:

SELECT DISTINCT first_name FROM employees;

DISTINCT位于SELECT之后,可以基于多个列值进行查重操作,通用语法如下:

SELECT DISTINCT
       column1,
       column2,
       ...
  FROM table;

为了消除重复值,数据库系统需要对结果进行排序,然后扫描重复值;因此,大量数据的重复值处理会降低查询的速度。

以上示例的结果如下(共计91条):
SQL从入门到出门 第3篇 初级查询
查询结果只有91条,而不是107条,这是因为 first_name 中有重复的数据。

DISTINCT对于多个NULL值,只会返回1条空值记录。例如:

SELECT DISTINCT commission_pct FROM employees;

使用列别名

在查询结果中,可以通过使用列别名为列指定一个临时的名称,以提高可读性。

SELECT c1 AS column_alias1, c2 column_alias2, FROM table;

关键字AS用于定义一个别名,也可以省略,只保留一个空格。

SELECT commission_pct AS 'Commission percentage' FROM employees;

当列别名中包含空格或者特殊字符时,需要将别名引用起来,不同的数据库产品使用不同的引用符号。

数据库 使用列别名 描述
Oracle OK                       Oracle返回大写的列名,对于包含空格的列别名使用双引号进行引用
MySQL OK MySQL对于包含空格的列别名支持单引号或者双引号或者反单引号(`)引用
SQL Server OK SQL Server对于包含空格的列别名支持单引号或者双引号或者中括号([ ])引用
PostgreSQL OK PostgreSQL返回小写的列名,对于包含空格的列别名使用双引号进行引用
Db2 OK 返回大写的列名,对于包含空格的列别名使用双引号进行引用
SQLite OK SQLite对于包含空格的列别名支持以上各种符号引用

除了列别名之外,SQL还支持表别名,我们将在介绍多表连接查询(JOIN)时解释表的别名。

SQL中的注释

在SQL中,可以像其他编程语言一样使用注释,注释不会被执行。

SQL中的注释分为单行注释和多行注释。

单行注释以两个连字符(–)开始,直到这一行结束。例如:

SELECT DISTINCT first_name -- distinct will remove duplicate records FROM employees;

多行注释使用C语言风格的注释方法(/* … */)。例如:

SELECT DISTINCT first_name /* distinct will remove duplicate records from results */ FROM employees;

除了SQL标准中的两种注释方式之外,不同数据库还提供了额外的扩展。

数据库 SQL中的注释 描述
Oracle OK                       Oracle中的特殊用法 –+ 和 /*+ hint */ 用于表示查询提示,参考Oracle文档
MySQL OK MySQL中的 # 也可以用单行注释;/*+ hint */ 用于优化器提示;/*! */ 也属于特殊用法
SQL Server OK
PostgreSQL OK
Db2 OK
SQLite OK