本文介绍关系数据库的设计思想:在 SQL 中,一切皆关系。html
在计算机领域有许多伟大的设计理念和思想,例如:sql
在 Unix 中,一切皆文件。数据库
在面向对象的编程语言中,一切皆对象。编程
关系数据库一样也有本身的设计思想:在 SQL 中,一切皆关系。数据结构
关系模型编程语言
关系模型(Relational model)由 E.F.Codd 博士于 1970 年提出,以集合论中的关系概念为基础;不管是现实世界中的实体对象仍是它们之间的联系都使用关系表示。咱们在数据库系统中看到的关系就是二维表(Table),由行(Row)和列(Column)组成。所以,也能够说关系表是由数据行构成的集合。ide
关系模型由数据结构、关系操做、完整性约束三部分组成。函数
关系模型中的数据结构就是关系表,包括基础表、派生表(查询结果)和虚拟表(视图)。.net
经常使用的关系操做包括增长、删除、修改和查询(CRUD),使用的就是 SQL 语言。其中查询操做最为复杂,包括选择(Selection)、投影(Projection)、并集(Union)、交集(Interp)、差集(Exception)以及笛卡儿积(Cartesian product)等。设计
完整性约束用于维护数据的完整性或者知足业务约束的需求,包括实体完整性(主键约束)、参照完整性(外键约束)以及用户定义的完整性(非空约束、惟一约束、检查约束和默认值)。
咱们今天的主题是关系操做语言,也就是 SQL。本文使用的示例数据来源于https://blog.csdn.net/horses/article/details/86518676。
面向集合
SQL(结构化查询语言)是操做关系数据库的标准语言。SQL 很是接近英语,使用起来很是简单。它在设计之初就考虑了非技术人员的使用需求,咱们一般只需说明想要的结果(What),而将数据处理的过程(How)交给数据库管理系统。因此说,SQL 才是真正给人用的编程语言!
接下来咱们具体分析一下关系的各类操做语句;目的是为了让你们可以了解 SQL 是一种面向集合的编程语言,它的操做对象是集合,操做的结果也是集合。
????在关系数据库中,关系、表、集合三者一般表示相同的概念。
下面是一个简单的查询语句:
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 中的示例:
-- PostgreSQLSELECT * 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 t2t2 LEFT JOIN t1
全外链接(Full Outer Join)等价于左外链接加上右外链接,同时返回左表和右表中全部的数据;对于两个表中不知足链接条件的数据返回空值。全外链接的原理以下图所示:
交叉链接也称为笛卡尔积(Cartesian Product)。两个表的交叉链接至关于一个表的全部行和另外一个表的全部行两两组合,结果的数量为两个表的行数相乘。交叉链接的原理以下图所示:
????其余类型的链接还有半链接(SEMI JOIN)、反链接(ANTI JOIN)。
集合操做将两个集合合并成一个更大或更小的集合;链接查询将两个集合转换成一个更大或更小的集合,同时得到了一个更大的元素(更多的列)。不少时候集合操做均可以经过链接查询来实现,例如:
SELECT department_id FROM departments UNIONSELECT 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); -- OracleINSERT INTO test(id)(SELECT 1 AS id FROM DUALUNION ALLSELECT 2 FROM DUALUNION ALLSELECT 3 FROM DUAL);
咱们经过一个 INSERT 语句插入了 3 条记录,或者说是插入了一个包含 3 条记录的关系表。由于,UNION ALL 返回的是一个关系表。VALUES 一样是指定了一个关系表,在 SQL Server 和 PostgreSQL 中支持如下语句:
SELECT *FROM ( VALUES(1),(2),(3)) test(id);
前面咱们已经说过,FROM 以后是一个关系表,因此这里的 VALUES 也是同样。因为咱们常常插入单条记录,并无意识到其实是以表为单位进行操做。
一样,UPDATE 和 DELETE 语句也都是以关系表为单位的操做;只不过咱们习惯了说更新一行数据或者删除几条记录。