上接:
写在前面的话:本文章内容是自己在LintCode网站SQL教程学习过程中做的学习总结,以便自己复习和大家学习,如果去刷此网站的题,也可以把此文作为参考答案来使用。例题的答案是本人所写,并且已经运行成功,大家可以放心学习。
目录
3.2 CREATE TABLE 时 添加 PRIMARY KEY 约束
4.4CREATE TABLE 时的 SQL FOREIGN KEY 约束
4.5 ALTER TABLE 时的 SQL FOREIGN KEY 约束
5.1 创建表(CREATE TABLE)时添加 CHECK约束
6.2 CREATE TABLE 时的 DEFAULT 约束
一.约束
在 SQL 中,约束是规定表中的数据规则。若存在违反约束的行为,行为就会阻止。它能帮助管理员更好地管理数据库,并且确保数据库中数据的正确性和有效性。例如在后台的数据库设计中对要输入的数据进行核查或判断,再决定是否写入数据库,这都是约束的应用。
1. 非空约束 NOT NULL
NOT NULL 约束强制列不接受 NULL 值,强制字段始终包含值,这意味着,如果不向字段添加值,就无法插入新纪录或者更新记录。
注意: 不要把 NULL 值与空字符串相混淆。NULL 值是没有值,它不是空字符串。如果指定' '(两个单引号,其间没有字符),这在 NOT NULL 列中是允许的。空串是一个有效的值,它不是无值。NULL 值用关键字 NULL 而不是空串指定。
2.唯一约束 UNIQUE
在前面的学习中我们知道了 NOT NULL 约束是强制列不接受 NULL 值,在有些情况下,我们不希望一个表中出现重复的记录,这时候我们需要用到 UNIQUE 约束来解决这些问题。
-
UNIQUE 约束唯一标识数据库表中的每条记录
-
UNIQUE 和 主键约束均为列或列集合提供了唯一性的保证
-
主键约束会自动定义一个 UNIQUE 约束,或者说主键约束是一种特殊的 UNIQUE 约束。但是二者有明显的区别:每个表可以有多个 UNIQUE 约束,但只能有一个主键约束。
2.1 CREATE TABLE 时的 UNIQUE 约束
下面的 SQL 在 Persons
表创建时在 P_Id
列上创建 UNIQUE 约束:
MySQL
CREATE TABLE `Persons`
(
`P_Id` int NOT NULL,
`LastName` varchar(255) NOT NULL,
`FirstName` varchar(255),
`Address` varchar(255),
`City` varchar(255),
UNIQUE (`P_Id`)
)
SQL Server / Oracle / MS Access
CREATE TABLE `Persons`
(
`P_Id` int NOT NULL UNIQUE,
`LastName` varchar(255) NOT NULL,
`FirstName` varchar(255),
`Address` varchar(255),
`City` varchar(255)
)
命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束:
MySQL / SQL Server / Oracle / MS Access
CREATE TABLE `Persons`
(
`P_Id` int NOT NULL,
`LastName` varchar(255) NOT NULL,
`FirstName` varchar(255),
`Address` varchar(255),
`City` varchar(255),
CONSTRAINT uc_PersonID UNIQUE (`P_Id`,`LastName`)
)
2.2 ALTER TABLE 时的 UNIQUE 约束
当表已被创建时,在 P_Id
列创建 UNIQUE 约束:
MySQL / SQL Server / Oracle / MS Access
ALTER TABLE `Persons`
ADD UNIQUE(`P_Id`)
当表已被创建时,需命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束:
MySQL / SQL Server / Oracle / MS Access
ALTER TABLE `Persons`
ADD CONSTRAINT uc_PersonID UNIQUE (`P_Id`,`LastName`)
2.3 撤销 UNIQUE 约束
如需撤销 UNIQUE 约束 :
MySQL
ALTER TABLE `Persons`
DROP INDEX uc_PersonID
SQL Server / Oracle / MS Access
ALTER TABLE `Persons`
DROP CONSTRAINT uc_PersonID
3. 主键约束 PRIMARY KEY
3.1 初识主键约束
主键约束,也叫 PRIMARY KEY 约束。
PRIMARY KEY 约束唯一标识数据库表中的每条记录 ,简单的说,PRIMARY KEY = UNIQUE + NOT NULL ,从技术的角度来看,PRIMARY KEY 和 UNIQUE 有很多相似之处。但还是有以下区别:
-
NOT NULL UNIQUE 可以将表的一列或多列定义为唯一性属性,而 PRIMARY KEY 设为多列时,仅能保证多列之和是唯一的,具体到某一列可能会重复。
-
PRIMARY KEY 可以与外键配合,从而形成主从表的关系,而 NOT NULL UNIQUE 则做不到这一点
如:
表一:用户
id
(主键),用户名表二: 银行卡号
id
(主键),用户id
(外键)则表一为主表,表二为从表。
-
更大的区别在逻辑设计上。 PRIMARY KEY 一般在逻辑设计中用作记录标识,这也是设置 PRIMARY KEY 的本来用意,而 UNIQUE 只是为了保证域/域组的唯一性。
3.2 CREATE TABLE 时 添加 PRIMARY KEY 约束
前面我们创建了个人信息数据表 Persons
,我们希望每个人的标识符 P_Id
都是唯一的。 下面的 SQL 在 个人信息表 Persons
创建时,在 P_Id
列上添加 PRIMARY KEY 约束:
MYSQL
CREATE TABLE `Persons`
(
`P_Id` int NOT NULL,
`LastName` varchar(255) NOT NULL,
`FirstName` varchar(255),
`Address` varchar(255),
`City` varchar(255),
PRIMARY KEY (`P_Id`)
);
SQL Server / Oracle / MS Access
CREATE TABLE `Persons`
(
`P_Id` int NOT NULL PRIMARY KEY,
`LastName` varchar(255) NOT NULL,
`FirstName` varchar(255),
`Address` varchar(255),
`City` varchar(255)
)
上述语句中 NOT NULL 为非空约束,即输入值必须不为空否则会报错。
如需命名并定义多个列的 PRIMARY KEY 约束,请使用下面的 SQL 语法:
CREATE TABLE `Persons`
(
`P_Id` int NOT NULL,
`LastName` varchar(255) NOT NULL,
`FirstName` varchar(255),
`Address` varchar(255),
`City` varchar(255),
CONSTRAINT pk_PersonID PRIMARY KEY (`P_Id`,`LastName`)
)
注释: 在上面的实例中,只有一个主键 PRIMARY KEY(pk_PersonID)。然而,pk_PersonID 的值是由两个列(
P_Id
和LastName
)组成的。
3.3 ALTER TABLE 时添加主键约束
当表已被创建时,如需在 P_Id
列创建 PRIMARY KEY 约束:
MySQL / SQL Server / Oracle / MS Access
ALTER TABLE `Persons`
ADD PRIMARY KEY (`P_Id`)
如需命名并定义多个列的 PRIMARY KEY 约束,可以使用下面的 SQL 语法:
MySQL / SQL Server / Oracle / MS Access
ALTER TABLE `Persons`
ADD CONSTRAINT pk_PersonID PRIMARY KEY (`P_Id`,`LastName`)
注释:
如果您使用 ALTER TABLE 语句添加主键,必须把主键列声明为不包含 NULL 值(在表首次创建时)。
3.4 撤销 PRIMARY KEY
如需撤销 PRIMARY KEY 约束,我们可以通过将上述 ALTER TABLE 和 DROP 实现:
MYSQL
ALTER TABLE `Persons`
DROP PRIMARY KEY
SQL Server / Oracle / MS Access
ALTER TABLE `Persons`
DROP CONSTRAINT pk_PersonID
例题1:在创建数据表时,因为数据库工作人员忘记添加主键约束,现在我们需要对课程表 courses
添加主键约束,将 id
列设置为主键,请编写相应的 SQL 语句。
答案:
alter table courses
add primary key(id)
例题2:请编写 SQL 语句,删除课程表 courses
中的主键约束。
答案:
alter table courses
drop primary key
4. 外键约束 FOREIGN KEY
4.1 什么是外键
如果一个字段 X 在一张表(表 1 )中是关键字,而在另一张表(表 2 )中不是关键字,则称字段 X 为表 2 的外键。
4.2 外键的作用
外键最根本的作用:保证数据的完整性和一致性。 通过一个例子来深入理解一下。 现在有两张表——学生表和院系表,这里的院系就是学生表的外键,外键表是学生表,主键表是院系表。假如院系表中的某个院系被删除了,那么在学生表中要想查询这个被删除的院系号所对应的院信息就会报错,因为已经不存在这个系了,所以,删除院系表(主键表)时必须删除其他与之关联的表,这里就说明了外键的作用,保持数据的一致性、完整性。当然反过来讲,你删除学生表中的记录,并不影响院系表中的数据,你查询院系号也能正确查询。所以删除外键表中的数据并不影响主键表。
4.3 外键约束
外键约束是指用于在两个表之间建立关系,需要指定引用主表的哪一列。
4.4CREATE TABLE 时的 SQL FOREIGN KEY 约束
在 "Orders" 表创建时在 "P_Id" 列上创建 FOREIGN KEY 约束:
MySQL
CREATE TABLE `Orders`
(
`O_Id` int NOT NULL,
`OrderNo` int NOT NULL,
`P_Id` int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
SQL Server / Oracle / MS Access
CREATE TABLE `Orders`
(
`O_Id` int NOT NULL PRIMARY KEY,
`OrderNo` int NOT NULL,
P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
)
其中
NOT NULL 表示该字段不为空 REFERENCES 表示 引用一个表
如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束:
MySQL / SQL Server / Oracle / MS Access
CREATE TABLE `Orders`
(
`O_Id` int NOT NULL,
`OrderNo` int NOT NULL,
`P_Id` int,
PRIMARY KEY (O_Id),
CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
)
其中
CONSTRAINT 表示约束,后面接约束名称,常用于创建约束和删除约束;
4.5 ALTER TABLE 时的 SQL FOREIGN KEY 约束
当 "Orders" 表已被创建时,如需在 "P_Id" 列创建 FOREIGN KEY 约束:
MySQL / SQL Server / Oracle / MS Access
ALTER TABLE `Orders`
ADD FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束:
MySQL / SQL Server / Oracle / MS Access
ALTER TABLE `Orders`
ADD CONSTRAINT fk_PerOrders
FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
4.6撤销 FOREIGN KEY 约束
如需撤销 FOREIGN KEY 约束:
MySQL
ALTER TABLE `Orders`
DROP FOREIGN KEY fk_PerOrders
SQL Server / Oracle / MS Access
ALTER TABLE `Orders`
DROP CONSTRAINT fk_PerOrders
例题:请编写 SQL 语句,为课程表 courses
中的 teacher_id
添加外键约束,使之能与教师表 teachers
中的 id
相关联。
答案:
alter table courses
add foreign key (teacher_id)
references teachers(id)
5. 检查约束 CHECK
CHECK 约束用于限制列中的值的范围,评估插入或修改后的值。满足条件的值将会插入表中,否则将放弃插入操作。 可以为同一列指定多个 CHECK 约束。
CHECK
约束既可以用于某一列也可以用于某张表:
-
如果对单个列定义 CHECK 约束,那么该列只允许特定的值。
-
如果对一个表定义 CHECK 约束,那么此约束会基于行中其他列的值在特定的列中对值进行限制。
定义 CHECK 约束条件在某种程度上类似于编写查询的 WHERE 子句,使用不同的比较运算符(例如 AND、OR、BETWEEN、IN、LIKE 和 IS NULL)编写其布尔表达式,该布尔表达式将返回 TRUE、FALSE 或 UNKNOWN 。 当条件中存在 NULL 值时,CHECK约束将返回 UNKNOWN 值。 CHECK 约束主要用于通过将插入的值限制为遵循定义的值、范围或格式规则的值来强制域完整性。
5.1 创建表(CREATE TABLE)时添加 CHECK约束
-
在创建课程表
courses
时,给学生总数student_count
字段加上一个大于 0 的约束。
MYSQL:
CREATE TABLE `courses`
(
`id` int,
`name` varchar(255),
`student_count` int,
`created_at` date,
`teacher_id` int,
CHECK (`student_count` > 0)
)
SQL Server / Oracle / MS Access:
CREATE TABLE `courses`
(
`id` int,
`name` varchar(255),
`student_count` int CHECK (`student_count` > 0),
`created_at` date,
`teacher_id` int
)
字段添加约束,直接在 CHECK 关键字后的括号内添加,两个约束间使用 AND 关键字连接。
-
为 CHECK 约束命名
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE `courses`
(
`id` int,
`name` varchar(255),
`student_count` int,
`created_at` date,
`teacher_id` int,
CONSTRAINT chk_courses CHECK (`student_count` > 0) ;
核心部分的基本语法为:
[CONSTRAINT <constraint name>] CHECK (<condition>)
其中:
约束关键字 CONSTRAINT:表示其后面接的内容为约束
constraint name:为约束名称
关键字 CHECK:表示检查约束
condition:被约束内容
5.2 表已存在时添加 CHECK 约束
-
课程表
courses
已存在的情况下为学生总数student_count
字段添加一个大于 0 的 CHECK 约束。
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE `courses`
ADD CHECK ( `student_count` > 0);
或
ALTER TABLE `courses`
ADD CONSTRAINT chk_courses CHECK ( `student_count` > 0);
ALTER TABLE 关键字:表示修改表的定义
ADD 关键字:表示增加
5.3撤销 CHECK 约束
-
如果想要撤销 CHECK 约束,可以使用 DROP 关键字。
MYSQL:
ALTER TABLE `courses`
DROP CHECK chk_courses
SQL Server / Oracle / MS Access:
ALTER TABLE `courses`
DROP CONSTRAINT chk_courses
6.默认约束 DEFAULT
默认值(Default)”的完整称呼是“默认值约束(Default Constraint)”。MySQL 默认值约束用来指定某列的默认值。
6.1 DEFAULT 约束用法
-
DEFAULT 约束用于向列中插入默认值。
-
如果没有规定其他的值,那么会将默认值添加到所有的新记录。
-
例如女同学较多,性别就可以默认为“女”,如果插入一条新的记录时没有为这个字段赋值,那么系统会自动为这个字段赋值为“女”。
6.2 CREATE TABLE 时的 DEFAULT 约束
-
使用 DEFAULT 关键字设置默认值约束,具体的语法规则如下所示:
<字段名> <数据类型> DEFAULT <默认值>
MYSQL / SQL Server / Oracle / MS Access
CREATE TABLE `Persons`
(
`P_Id` int NOT NULL,
`LastName` varchar(255) NOT NULL,
`FirstName` varchar(255),
`Address` varchar(255),
`City` varchar(255) DEFAULT 'Sandnes'
)
👇通过使用类似 GETDATE() 这样的函数, DEFAULT 约束也可以用于插入系统值:
CREATE TABLE `Orders`
(
`O_Id` int NOT NULL,
`OrderNo` int NOT NULL,
`P_Id` int,
`OrderDate` date DEFAULT GETDATE()
)
6.3 ALTER TABLE 时的 DEFAULT 约束
如果表已被创建时,想要在 City
列创建 DEFAULT 约束,请使用下面的 SQL:
MYSQL
ALTER TABLE `Persons`
ALTER `City` SET DEFAULT 'SANDNES'
SQL Server / MS Access:
ALTER TABLE `Persons`
ADD CONSTRAINT ab_c DEFAULT 'SANDNES' for `City`
6.4 撤销 DEFAULT 约束
如需撤销 Persons
表的 DEFAULT 约束 :
MYSQL:
ALTER TABLE `Persons`
ALTER `City` DROP DEFAULT
SQL Server / Oracle / MS Access:
ALTER TABLE `Persons`
ALTER COLUMN `City` DROP DEFAULT
二.多表连接
1.联结
1.1什么叫联结?
SQL 最强大的功能之一就是能在数据检索查询的执行中联结表。联结是一种机制,用于在一条 SELECT 语句中关联多个表,返回一组输出。
1.2怎么创建联结?
规定要联结的所有表以及它们如何关联就可以了。
在设置关联条件时,为避免不同表被引用的列名相同,我们需要使用完全限定列名(用一个点分隔表名和列名),否则会返回错误。
用法如下:
`table1`.`common_field` = `table2`.`common_field`
举个例子,教师表的主键 id
为设置的关联条件为:
`teachers`.`id` = `courses`.`teacher_id`
1.3JOIN 连接子句
SQL JOIN 连接子句用于将数据库中两个或者两个以上表中的记录组合起来。其类型主要分为 INNER JOIN(内连接)、OUTER JOIN(外连接)、全连接(FULL JOIN)和交叉连接(CROSS JOIN),其中 OUTER JOIN 又可以细分为 LEFT JOIN(左连接)和 RIGHT JOIN(右连接)。
因此,我们主要使用的 JOIN 连接类型如下:
-
INNER JOIN:如果表中有至少一个匹配,则返回行
-
LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行
-
RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行
-
FULL JOIN:只要其中一个表中存在匹配,则返回行
-
CROSS JOIN:又称笛卡尔积,两个表数据一一对应,返回结果的行数等于两个表行数的乘积
2. 内连接 INNER JOIN
最常用也最重要的多表联结类型就是 INNER JOIN(内连接),有时候也被称作 EQUIJOIN(等值连接)。
内连接根据联结条件来组合两个表中的字段,以创建一个新的结果表。假如我们想将表 1 和表 2 进行内连接,SQL 查询会逐个比较表 1 和表 2 中的每一条记录,来寻找满足联结条件的所有记录对。当联结条件得以满足时,所有满足条件的记录对的字段将会结合在一起构成结果表。
简单的说,内连接就是取两个表的交集,返回的结果就是连接的两张表中都满足条件的部分。
基本语法
在对 INNER JOIN(内连接)的概念有基本的了解之后,我们再来学习一下它的基本语法。 基本语法有如下两种写法:
SELECT `table1`.`column1`, `table2`.`column2`...
FROM `table1`
INNER JOIN `table2`
ON `table1`.`common_field` = `table2`.`common_field`;
或
SELECT `table1`.`column1`, `table2`.`column2`...
FROM `table1`
JOIN `table2`
ON `table1`.`common_field` = `table2`.`common_field`;
注:INNER JOIN 中 INNER 可以省略不写
其中,语法的核心部分如下所示:
FROM table1
INNER JOIN table2
ON table1.common_field = table2.common_field
table1
和 table2
是内连接的两个表名,table1
.common_field
和 table2
.common_field
需要注意的是,联结条件需使用特定的 ON 子句给出。
举个例子:
SELECT `c`.`id`, `c`.`name` AS `course_name`, `t`.`name` AS `teacher_email`
FROM `courses` `c`
INNER JOIN `teachers` `t`
ON `c`.`teacher_id` = `t`.`id`;
-
courses
c
等同于courses
ASc
,给courses
表取别名为c
-
teachers
t
等同于teachers
ASt
,给teachers
表取别名为t
-
INNER JOIN 也可写作 JOIN
例题:请编写 SQL 语句,将课程表 courses
和教师表 teachers
进行内连接,查询 “Eastern Heretic” 老师所教的所有课程的课程名和课程编号 , 且结果列名分别以课程编号 id
、课程名称 course_name
和教师姓名 teacher_name
显示。
答案:
select courses.id,courses.name as course_name,teachers.name as teacher_name
from courses
join teachers
on courses.teacher_id=teachers.id
where teachers.name= 'Eastern Heretic'
3. 外连接 OUTER JOIN
外连接也是针对于两张表格之间,外连接可以将某个表格中,在另外一张表格中无对应关系,但是也能将数据匹配出来。
在MySQL中,外连接查询会返回所操作的表中至少一个表的所有数据记录。在MySQL中,数据查询通过SQL语句 “OUTER JOIN…ON” 来实现,外连接查询可以分为以下三类:
-
左外连接
-
右外连接
-
全外连接
外连接数据查询语法如下:
SELECT column_name 1,column_name 2 ... column_name n
FROM table1
LEFT | RIGHT | FULL (OUTER) JOIN table2
ON CONDITION;
在上述语句中,参数 column_name 表示所要查询的字段名字,来源于所连接的表 table1 和 table2,关键字 OUTER JOIN 表示表进行外连接,参数 CONDITION 表示进行匹配的条件。
3.1 左外连接 LEFT JOIN
外连接查询中的左外连接就是指新关系中执行匹配条件时,以关键字 LEFT JOIN 左边的表为参考表。左外连接的结果包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是连接列所匹配的行,这就意味着,左连接会返回左表中的所有记录,加上右表中匹配到的记录。如果左表的某行在右表中没有匹配行,那么在相关联的结果行中,右表的所有选择列表均为空值。
语法:
SELECT column_name 1,column_name 2 ... column_name n
FROM table1
LEFT JOIN table2
ON CONDITION ;
例题:请编写 SQL 语句,将教师表 teachers
和课程表 courses
进行左连接,查询来自中国(讲师国籍 country
='CN' )的教师名称以及所教课程名称,结果列名请分别以课程名称 course_name
,教师名称 teacher_name
显示。
答案:
select c.name as course_name,t.name as teacher_name
from teachers t
left join courses c
on t.id=c.teacher_id
where t.country='CN'
3.2 右外连接 RIGHT JOIN
外连接查询中的右外连接是指新关系中执行匹配条件时,以关键字 RIGHT JOIN 右边的表为参考表,如果右表的某行在左表中没有匹配行,左表就返回空值。
语法:
SELECT column_name 1,column_name 2 ... column_name n
FROM table1
RIGHT JOIN table2
ON CONDITION ;
例题:请编写 SQL 语句,将课程表 courses
和教师表 teachers
进行右连接,查询来自中国(讲师国籍 country
='CN' )的教师姓名,邮箱以及所教课程名称,结果列名请分别以课程名称 course_name
,教师名称 teacher_name
,教师邮箱 teacher_email
显示。
答案:
select c.name as course_name,t.name as teacher_name,t.email as teacher_email
from courses c
right join teachers t
on t.id=c.teacher_id
where t.country='CN'
3.3 全外连接 FULL (OUTER) JOIN
FULL OUTER JOIN 关键字只要左表(table1)和右表(table2)其中一个表中存在匹配,则返回行。FULL OUTER JOIN 关键字结合了 LEFT JOIN 和 RIGHT JOIN 的结果。
注:MySQL 数据库不支持全连接,想要实现全连接可以使用 UNION ALL 来将左连接和右连接结果组合在一起实现全连接。
UNION :联合的意思,即把两次或多次查询结果合并起来
要求:两次查询的列数必须一致,同时,每条 SELECT 语句中的列的顺序必须相同
推荐:列的类型可以不一样,但推荐查询的每一列,相对于的类型应该一样
可以来自多张表的数据:多次sql语句取出的列名可以不一致,此时以第一个sql语句的列名为准,即UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。 如果不同的语句中取出的行,有完全相同(这里表示的是每个列的值都相同),那么 UNION 会将相同的行合并,最终只保留一行。也可以这样理解,UNION 会去掉重复的行。 如果不想去掉重复的行,可以使用 UNION ALL 。 如果子句中有 order by,limit,需用括号()包起来。推荐放到所有子句之后,即对最终合并的结果来排序或筛选。
语法:
SELECT column_name 1,column_name 2 ... column_name n
FROM table1
LEFT JOIN table2 ON CONDITION
UNION
SELECT column_name 1,column_name 2 ... column_name n
FROM table1
RIGHT JOIN table2 ON CONDITION ;
例题:请编写 SQL 语句,将课程表 courses
和教师表 teachers
进行外连接,查询所有课程名称以及与其相互对应的教师名称和教师国籍,结果列名请分别以课程名称 course_name
、教师名称 teacher_name
、教师国籍 teacher_country
显示。
答案:
select c.name as course_name,t.name as teacher_name,t.country as teacher_country
from teachers t
left join courses c
on t.id=c.teacher_id
union
select c.name as course_name,t.name as teacher_name,t.country as teacher_country
from teachers t
right join courses c
on t.id=c.teacher_id
4. 交叉连接 CROSS JOIN
4.1 什么是交叉连接
与内连接和外连接相比,交叉连接非常简单,因为它不存在 ON 子句,那怎么理解交叉连接呢?
交叉连接:返回左表中的所有行,左表中的每一行与右表中的所有行组合。即将两个表的数据一一对应,其查询结果的行数为左表中的行数乘以右表中的行数。
CROSS JOIN(交叉连接)的结果也称作笛卡尔积,我们来简单了解一下什么是笛卡尔积:
笛卡尔乘积是指在数学中,两个集合 X 和 Y 的笛卡尓积(Cartesian product),又称直积,表示为X × Y,第一个对象是 X 的成员而第二个对象是 Y 的所有可能有序对的其中一个成员。
4.2 交叉连接的两种定义方式
交叉连接有两种定义方式,分为隐式连接和显式连接。两种定义方式的查询结果是相同的。
-
隐式交叉连接:不需要使用 CROSS JOIN 关键字,只要在 SELECT 语句的 FROM 语句后将要进行交叉连接的表名列出即可,这种方式基本上可以被任意数据库系统支持。
基本语法如下:
SELECT `table1`.`column1`, `table2`.`column2`...
FROM `table1`,`table2`;
-
显式交叉连接:与隐式交叉连接的区别就是它使用 CROSS JOIN 关键字,用法与 INNER JOIN 相似。
基本语法如下:
SELECT `table1`.`column1`, `table2`.`column2`...
FROM `table1`
CROSS JOIN `table2`;
通过执行结果我们可以发现笛卡尔积存在多条无效错误数据且很冗杂,我们需要怎么改进,才能使交叉连接发挥出它的力量呢?
增加联结条件,使用 WHERE 子句帮助筛选过滤无效的数据!
增加 WHERE 子句后,上述语句可以发挥出等同于内连接 INNER JOIN 的作用。