1. 基本概念

1.1 数据库术语

  • 数据库(database) :保存有组织的数据的容器(通常是一个文件或一组文件)。
  • 数据表(table) :某种特定类型数据的结构化清单。
  • 模式(schema) :关于数据库和表的布局及特性的信息。模式定义了数据在表中如何存储,包含存储什么样的数据,数据如何分解,各部分信息如何命名等信息。数据库和表都有模式。
  • 列(column) :表中的一个字段。所有表都是由一个或多个列组成的。
  • 行(row) :表中的一个记录。
  • 主键(primary key) :一列(或一组列),其值能够唯一标识表中每一行。

1.2 SQL 语法

SQL(Structured Query Language),标准 SQL 由 ANSI 标准委员会管理,从而称为 ANSI SQL。各个 DBMS 都有自己的实现,如 PL/SQL、Transact-SQL 等。

SQL 语法结构包括:

  • 子句:是语句和查询的组成成分。(在某些情况下,这些都是可选的。)
  • 表达式:可以产生任何标量值,或由列和行的数据库表
  • 谓词:给需要评估的 SQL 三值逻辑(3VL)(true/false/unknown)或布尔真值指定条件,并限制语句和查询的效果,或改变程序流程。
  • 查询:基于特定条件检索数据。这是 SQL 的一个重要组成部分。
  • 语句:可以持久地影响纲要和数据,也可以控制数据库事务、程序流程、连接、会话或诊断。

SQL 语法要点

  • SQL 语句不区分大小写,但是数据库表名、列名和值是否区分,依赖于具体的 DBMS 以及配置。例如:SELECT 与 select、Select 是相同的。
  • 多条 SQL 语句必须以分号(;)分隔
  • 处理 SQL 语句时,所有空格都被忽略

SQL 语句可以写成一行,也可以分写为多行。

-- 一行 SQL 语句
UPDATE user SET username='robot', password='robot' WHERE username = 'root';

-- 多行 SQL 语句
UPDATE user
SET username='robot', password='robot'
WHERE username = 'root';

SQL 支持三种注释:

## 注释1
-- 注释2
/* 注释3 */

1.3 SQL分类

1.3.1 数据定义语言(DDL)

数据定义语言(Data Definition Language,DDL)是 SQL 语言集中负责数据结构定义与数据库对象定义的语言。

DDL 的主要功能是定义数据库对象

DDL 的核心指令是 CREATE、ALTER、DROP

1.3.2 数据操纵语言(DML)

数据操纵语言(Data Manipulation Language, DML)是用于数据库操作,对数据库其中的对象和数据运行访问工作的编程语句。

DML 的主要功能是 访问数据,因此其语法都是以读写数据库为主。

DML 的核心指令是 INSERT、UPDATE、DELETE、SELECT。这四个指令合称 CRUD(Create, Read, Update, Delete),即增删改查。

1.3.3 事务控制语言(TCL)

事务控制语言 (Transaction Control Language, TCL) 用于管理数据库中的事务。这些用于管理由 DML 语句所做的更改。它还允许将语句分组为逻辑事务。

TCL 的核心指令是 COMMIT、ROLLBACK

1.3.4 数据控制语言(DCL)

数据控制语言 (Data Control Language, DCL) 是一种可对数据访问权进行控制的指令,它可以控制特定用户账户对数据表、查看表、预存程序、用户自定义函数等数据库对象的控制权。

DCL 的核心指令是 GRANT、REVOKE

DCL 以控制用户的访问权限为主,因此其指令作法并不复杂,可利用 DCL 控制的权限有:CONNECT、SELECT、INSERT、UPDATE、DELETE、EXECUTE、USAGE、REFERENCES

2. 增删改查

增删改查,又称为 CRUD,数据库基本操作中的基本操作。

2.1 插入数据

INSERT INTO 语句用于向表中插入新记录。

插入完整的行

# 插入一行
INSERT INTO user
VALUES (10, 'root', 'root', 'xxxx@163.com');
# 插入多行
INSERT INTO user
VALUES (10, 'root', 'root', 'xxxx@163.com'), (12, 'user1', 'user1', 'xxxx@163.com'), (18, 'user2', 'user2', 'xxxx@163.com');

插入行的一部分

INSERT INTO user(username, password, email)
VALUES ('admin', 'admin', 'xxxx@163.com');

插入查询出来的数据

INSERT INTO user(username)
SELECT name
FROM account;

2.2 更新数据

UPDATE 语句用于更新表中的记录。

UPDATE user
SET username='robot', password='robot'
WHERE username = 'root';

2.3 删除数据

  • DELETE 语句用于删除表中的记录。
  • TRUNCATE TABLE 可以清空表,也就是删除所有行。说明:TRUNCATE 语句不属于 DML 语法而是 DDL 语法。

删除表中的指定数据

DELETE FROM user
WHERE username = 'robot';

清空表中的数据

TRUNCATE TABLE user;

2.4 查询数据

  • SELECT 语句用于从数据库中查询数据。
  • DISTINCT 用于返回唯一不同的值。它作用于所有列,也就是说所有列的值都相同才算相同。
  • LIMIT 限制返回的行数。可以有两个参数,第一个参数为起始行,从 0 开始;第二个参数为返回的总行数。
    • ASC:升序(默认)
    • DESC:降序

查询单列

SELECT prod_name
FROM products;

查询多列

SELECT prod_id, prod_name, prod_price
FROM products;

查询所有列

SELECT *
FROM products;

查询不同的值

SELECT DISTINCT
vend_id FROM products;

限制查询结果

-- 返回前 5 行
SELECT * FROM mytable LIMIT 5;
SELECT * FROM mytable LIMIT 0, 5;
-- 返回第 3 ~ 5 行
SELECT * FROM mytable LIMIT 2, 3;

3. 排序

order by 用于对结果集按照一个列或者多个列进行排序。默认按照升序对记录进行排序,如果需要按照降序对记录进行排序,可以使用 desc 关键字。

order by 对多列排序的时候,先排序的列放前面,后排序的列放后面。并且,不同的列可以有不同的排序规则。

SELECT * FROM products
ORDER BY prod_price DESC, prod_name ASC;

4. 分组

group by

  • group by 子句将记录分组到汇总行中。
  • group by 为每个组返回一个记录。
  • group by 通常还涉及聚合count,max,sum,avg 等。
  • group by 可以按一列或多列进行分组。
  • group by 按分组字段进行排序后,order by 可以以汇总字段来进行排序。

4.1 分组

SELECT cust_name, COUNT(cust_address) AS addr_num
FROM Customers GROUP BY cust_name;

4.2 分组后排序

SELECT cust_name, COUNT(cust_address) AS addr_num
FROM Customers GROUP BY cust_name
ORDER BY cust_name DESC;

having

  • having 用于对汇总的 group by 结果进行过滤。
  • having 一般都是和 group by 连用。
  • wherehaving 可以在相同的查询中。

4.3 使用 WHERE 和 HAVING 过滤数据

SELECT cust_name, COUNT(*) AS NumberOfOrders
FROM Customers
WHERE cust_email IS NOT NULL
GROUP BY cust_name
HAVING COUNT(*) > 1;

having vs where

  • where过滤指定的行,后面不能加聚合函数(分组函数)。where 在group by 前。
  • having过滤分组,一般都是和 group by 连用,不能单独使用。having 在 group by 之后。

5. 子查询

子查询是嵌套在较大查询中的 SQL 查询,也称内部查询或内部选择,包含子查询的语句也称为外部查询或外部选择。简单来说,子查询就是指将一个 select 查询(子查询)的结果作为另一个 SQL 语句(主查询)的数据来源或者判断条件。

子查询可以嵌入 SELECT、INSERT、UPDATE 和 DELETE 语句中,也可以和 =、<、>、IN、BETWEEN、EXISTS 等运算符一起使用。

子查询常用在 WHERE 子句和 FROM 子句后边:

  • 当用于 WHERE 子句时,根据不同的运算符,子查询可以返回单行单列、多行单列、单行多列数据。子查询就是要返回能够作为 WHERE 子句查询条件的值。
  • 当用于 FROM 子句时,一般返回多行多列数据,相当于返回一张临时表,这样才符合 FROM 后面是表的规则。这种做法能够实现多表联合查询。

5.1 用于 WHERE 子句的子查询的基本语法

  • 子查询需要放在括号( )内。
  • operator 表示用于 where 子句的运算符。
select column_name [, column_name ]
from   table1 [, table2 ]
where  column_name operator
    (select column_name [, column_name ]
    from table1 [, table2 ]
    [where])

5.2 用于 FROM 子句的子查询的基本语法

用于 FROM 的子查询返回的结果相当于一张临时表,所以需要使用 AS 关键字为该临时表起一个名字。

select column_name [, column_name ]
from (select column_name [, column_name ]
      from table1 [, table2 ]
      [where]) as temp_table_name
where  condition

5.3 子查询的子查询

SELECT cust_name, cust_contact
FROM customers
WHERE cust_id IN (SELECT cust_id
                  FROM orders
                  WHERE order_num IN (SELECT order_num
                                      FROM orderitems
                                      WHERE prod_id = 'RGAN01'));

内部查询首先在其父查询之前执行,以便可以将内部查询的结果传递给外部查询。执行过程可以参考下图:
在这里插入图片描述

5.4 WHERE关键字

LIKE

  • LIKE 操作符在 WHERE 子句中使用,作用是确定字符串是否匹配模式。
  • 只有字段是文本值时才使用 LIKE
  • LIKE 支持两个通配符匹配选项:% _
  • 不要滥用通配符,通配符位于开头处匹配会非常慢。
  • % 表示任何字符出现任意次数。
  • _ 表示任何字符出现一次。

6. 连接

6.1 基本用法

JOIN 是“连接”的意思,顾名思义,SQL JOIN 子句用于将两个或者多个表联合起来进行查询。

连接表时需要在每个表中选择一个字段,并对这些字段的值进行比较,值相同的两条记录将合并为一条。连接表的本质就是将不同表的记录合并起来,形成一张新表。当然,这张新表只是临时的,它仅存在于本次查询期间

使用 JOIN 连接两个表的基本语法如下:

select table1.column1, table2.column2...
from table1
join table2
on table1.common_column1 = table2.common_column2;

table1.common_column1 = table2.common_column2 是连接条件,只有满足此条件的记录才会合并为一行。可以使用多个运算符来连接表,例如 =、>、<、<>、<=、>=、!=、between、like 或者 not,但是最常见的是使用 =

如果两张表的关联字段名相同,也可以使用 USING子句来代替 ON。

# join....on
select c.cust_name, o.order_num
from Customers c
inner join Orders o
on c.cust_id = o.cust_id
order by c.cust_name;

# 如果两张表的关联字段名相同,也可以使用USING子句:join....using()
select c.cust_name, o.order_num
from Customers c
inner join Orders o
using(cust_id)
order by c.cust_name;

ONWHERE 的区别:

  • 连接表时,SQL 会根据连接条件生成一张新的临时表。ON 就是连接条件,它决定临时表的生成。
  • WHERE 是在临时表生成以后,再对临时表中的数据进行过滤,生成最终的结果集,这个时候已经没有 JOIN-ON 了

总结:SQL 先根据 ON 生成一张临时表,然后再根据 WHERE 对临时表进行筛选。

6.2 JOIN类型

连接类型 说明
INNER JOIN 内连接 (默认连接方式)只有当两个表都存在满足条件的记录时才会返回行。
LEFT JOIN / LEFT OUTER JOIN 左(外)连接 返回左表中的所有行,即使右表中没有满足条件的行也是如此。
RIGHT JOIN / RIGHT OUTER JOIN 右(外)连接 返回右表中的所有行,即使左表中没有满足条件的行也是如此。
FULL JOIN / FULL OUTER JOIN 全(外)连接 只要其中有一个表存在满足条件的记录,就返回行。
SELF JOIN 将一个表连接到自身,就像该表是两个表一样。为了区分两个表,在 SQL 语句中需要至少重命名一个表。
CROSS JOIN 交叉连接,从两个或者多个连接表中返回记录集的笛卡尔积。

在这里插入图片描述
对于 INNER JOIN 来说,还有一种隐式的写法,称为 “隐式内连接”,也就是没有 INNER JOIN 关键字,使用 WHERE 语句实现内连接的功能

# 隐式内连接
select c.cust_name, o.order_num
from Customers c, Orders o
where c.cust_id = o.cust_id
order by c.cust_name;

# 显式内连接
select c.cust_name, o.order_num
from Customers c inner join Orders o
using(cust_id)
order by c.cust_name;

7. 组合

UNION 运算符将两个或更多查询的结果组合起来,并生成一个结果集,其中包含来自 UNION 中参与查询的提取行。

UNION 基本规则:

  • 所有查询的列数和列顺序必须相同。
  • 每个查询中涉及表的列的数据类型必须相同或兼容。
  • 通常返回的列名取自第一个查询。

默认地,UNION操作符选取不同的值。如果允许重复的值,请使用 UNION ALL

SELECT column_name(s) FROM table1
UNION ALL
SELECT column_name(s) FROM table2;
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐