在计算机领域有许多平凡的设计理念和思维,例如:
- 在 Unix 中,所有皆文件。
- 在面向对象的编程语言中,所有皆对象。
关系数据库同样也有本人的设计思维:在 SQL 中,所有皆关系。
关系模型
关系模型(Relational model)由 E.F.Codd 博士于 1970 年提出,以集合论中的关系概念为根底;无论是事实世界中的实体对象还是它们之间的分割都应用关系示意。咱们在数据库系统中看到的关系就是二维表(Table),由行(Row)和列(Column)组成。因而,也能够说关系表是由数据行形成的汇合。
关系模型由 数据结构 、 关系操作 、 完整性束缚 三局部组成。
- 关系模型中的数据结构就是关系表,包含 根底表 、 派生表 (查问后果)和 虚构表(视图)。
- 罕用的关系操作包含 减少 、 删除 、 批改 和查问(CRUD),应用的就是 SQL 语言。其中查问操作最为简单,包含抉择(Selection)、投影(Projection)、并集(Union)、交加(Intersection)、差集(Exception)以及笛卡儿积(Cartesian product)等。
- 完整性束缚用于保护数据的完整性或者满足业务束缚的需要,包含 实体完整性 (主键束缚)、 参照完整性 (外键束缚)以及 用户定义的完整性(非空束缚、惟一束缚、查看束缚和默认值)。
咱们明天的主题是关系操作语言,也就是 SQL。本文应用的示例数据来源于这篇文章。
面向汇合
SQL(结构化查询语言)是操作关系数据库的规范语言。SQL 十分靠近英语,应用起来非常简单。它在设计之初就思考了非技术人员的应用需要,咱们通常只需阐明想要的后果(What),而将数据处理的过程(How)交给数据库管理系统。所以说,SQL 才是真正给人用的编程语言!😎
接下来咱们具体分析一下关系的各种操作语句;目标是为了让大家可能理解 SQL 是一种面向汇合的编程语言,它的操作对象是汇合,操作的后果也是汇合。
📝在关系数据库中,关系、表、汇合三者通常示意雷同的概念。
SELECT
上面是一个简略的查问语句:
SELECT employee_id, first_name, last_name, hire_date
FROM employees;
它的作用就是从 employees 表中查问员工信息。显然,咱们都晓得 FROM 之后是一个表(关系、汇合)。不仅如此,整个查问语句的后果也是一个表。所以,咱们能够将下面的查问作为表应用:
SELECT *
FROM (SELECT employee_id, first_name, last_name, hire_date
FROM employees) t;
括号内的查问语句被称为派生表,咱们给它指定了一个别名叫做 t。同样,整个查问后果也是一个表;这就意味着咱们能够持续嵌套,尽管这么做很无聊。
咱们再看一个 PostgreSQL 中的示例:
-- PostgreSQL
SELECT *
FROM upper('sql');
| upper |
|-------|
| SQL |
upper() 是一个大写转换的函数。它呈现再 FROM 子句中,意味着它的后果也是一个表,只不过是 1 行 1 列的非凡表。
SELECT 子句用于指定须要查问的字段,能够蕴含表达式、函数值等。SELECT 在关系操作中被称为投影(Projection),看上面的示意图应该就比拟好了解了。
除了 SELECT 之外,还有一些罕用的 SQL 子句。
WHERE 用于指定数据过滤的条件,在关系运算中被称为抉择(Selection),示意图如下:
ORDER BY 用于对查问的后果进行排序,示意图如下:
总之,SQL 能够实现各种数据操作,例如过滤、分组、排序、限定数量等;所有这些操作的对象都是关系表,后果也是关系表。
在这些关系操作中,有一个比拟非凡,就是分组。
GROUP BY
分组(GROUP BY)操作和其余的关系操作不同,因为它扭转了关系的构造。来看上面的示例:
SELECT department_id, count(*), first_name
FROM employees
GROUP BY department_id;
该语句的目标是依照部门统计员工的数量,然而存在一个语法错误,就是 first_name 不能呈现在查问列表中。起因在于依照部门进行分组的话,每个部门蕴含多个员工;无奈确定须要显示哪个员工的姓名,这是一个逻辑上的谬误。
所以说,GROUP BY 扭转了汇合元素(数据行)的构造,创立了一个全新的关系。分组操作的示意图如下:
尽管如此,GROUP BY 的后果依然是一个汇合。
UNION
SQL 面向汇合个性最显著的体现就是 UNION(并集运算)、INTERSECT(交加运算)和 EXCEPT/MINUS(差集运算)。
这些汇合运算符的作用都是将两个汇合并成一个汇合,因而须要满足以下条件:
- 两边的汇合中字段的数量和程序必须雷同;
- 两边的汇合中对应字段的类型必须匹配或兼容。
具体来说,UNION 和 UNION ALL 用于计算两个汇合的并集,返回呈现在第一个查问后果或者第二个查问后果中的数据。它们的区别在于 UNION 排除了后果中的反复数据,UNION ALL 保留了反复数据。上面是 UNION 操作的示意图:
INTERSECT 操作符用于返回两个汇合中的独特局部,即同时呈现在第一个查问后果和第二个查问后果中的数据,并且排除了后果中的反复数据。INTERSECT 运算的示意图如下:
EXCEPT 或者 MINUS 操作符用于返回两个汇合的差集,即呈现在第一个查问后果中,但不在第二个查问后果中的记录,并且排除了后果中的反复数据。EXCEPT 运算符的示意图如下:
除此之外,DISTINCT 运算符用于打消反复数据,也就是排除汇合中的反复元素。
📝SQL 中的关系概念来自数学中的汇合实践,因而 UNION、INTERSECT 和 EXCEPT 别离来自集合论中的并集($\cup$)、交加($\cap$)和差集($\setminus$)运算。须要留神的是,汇合实践中的汇合不容许存在反复的数据,然而 SQL 容许。因而,SQL 中的汇合也被称为多重汇合(multiset);多重汇合与汇合实践中的汇合都是无序的,然而 SQL 能够通过 ORDER BY 子句对查问后果进行排序。
JOIN
在 SQL 中,不仅实体对象存储在关系表中,对象之间的分割也存储在关系表中。因而,当咱们想要获取这些相干的数据时,须要应用到另一个操作:连贯查问(JOIN)。
常见的 SQL 连贯查类型包含 内连贯 、 外连贯 、 穿插连贯 等。其中,外连贯又能够分为 左外连贯 、 右外连贯 以及 全外连贯。
内连贯(Inner Join)返回两个表中满足连贯条件的数据,内连贯的原理如下图所示:
左外连贯(Left Outer Join)返回左表中所有的数据;对于右表,返回满足连贯条件的数据;如果没有就返回空值。左外连贯的原理如下图所示:
右外连贯(Right Outer Join)返回右表中所有的数据;对于左表,返回满足连贯条件的数据,如果没有就返回空值。右外连贯与左外连贯能够调换,以下两者等价:
t1 RIGHT JOIN t2
t2 LEFT JOIN t1
全外连贯(Full Outer Join)等价于左外连贯加上右外连贯,同时返回左表和右表中所有的数据;对于两个表中不满足连贯条件的数据返回空值。全外连贯的原理如下图所示:
穿插连贯也称为笛卡尔积(Cartesian Product)。两个表的穿插连贯相当于一个表的所有行和另一个表的所有行两两组合,后果的数量为两个表的行数相乘。穿插连贯的原理如下图所示:
📝其余类型的连贯还有半连贯(SEMI JOIN)、反连贯(ANTI JOIN)。
汇合操作将两个汇合合并成一个更大或更小的汇合;连贯查问将两个汇合转换成一个更大或更小的汇合,同时取得了一个更大的元素(更多的列)。很多时候汇合操作都能够通过连贯查问来实现,例如:
SELECT department_id
FROM departments
UNION
SELECT department_id
FROM employees;
等价于:
SELECT COALESCE(d.department_id, e.department_id)
FROM departments d
FULL JOIN employees e ON (e.department_id = d.department_id);
咱们曾经介绍了许多查问的示例,接下来看看其余的数据操作。
DML
DML 示意数据操作语言,也就是插入、更新和删除。以下是一个插入语句示例:
CREATE TABLE test(id int);
-- MySQL、SQL Server 等
INSERT INTO test(id) VALUES (1),(2),(3);
-- Oracle
INSERT INTO test(id)
(SELECT 1 AS id FROM DUAL
UNION ALL
SELECT 2 FROM DUAL
UNION ALL
SELECT 3 FROM DUAL);
咱们通过一个 INSERT 语句插入了 3 条记录,或者说是插入了一个蕴含 3 条记录的关系表。因为,UNION ALL 返回的是一个关系表。VALUES 同样是指定了一个关系表,在 SQL Server 和 PostgreSQL 中反对以下语句:
SELECT *
FROM (VALUES(1),(2),(3)
) test(id);
后面咱们曾经说过,FROM 之后是一个关系表,所以这里的 VALUES 也是一样。因为咱们常常插入单条记录,并没有意识到实际上是以表为单位进行操作。
同样,UPDATE 和 DELETE 语句也都是以关系表为单位的操作;只不过咱们习惯了说更新一行数据或者删除几条记录。
如果感觉文章对你有用,请不要白嫖!欢送关注❤️、点赞👍、转发📣!