# 多表操作
```sql
--建表 table1,table2:
create table table1(id int, name varchar(10))
insert into table1 select 1, 'lee'
insert into table1 select 2, 'zhang'
insert into table1 select 4, 'wang'
create table table2(id int, score int)
insert into table2 select 1, 90
insert into table2 select 2, 100
insert into table2 select 3, 70
```
如表
table1 |
table2 |
id |
name |
id |
score |
1 |
lee |
1 |
90 |
2 |
zhang |
2 |
100 |
4 |
wang |
3 |
70 |
以下均在查询分析器中执行
## 一、内连接
### 1、概念
内联接:也称等值连接,返回两张表都满足连接条件的部分
> 注释:inner join 就等于 join
### 2、SQL 语句
```sql
select * from table1 inner join table2 on table1.id = table2.id
```
结果
id |
name |
id |
score |
1 |
lee |
1 |
90 |
2 |
zhang |
2 |
100 |
> 注释:只返回符合条件的 table1 和 table2 的列
与下列执行结果相同
```sql
A: select a.*, b.* from table1 a, table2 b where a.id = b.id
B: select * from table1 cross join table2 where table1.id = table2.id
```
> 注释:现已不建议使用 A 方法进行内连接取数,cross join 后加条件只能用 where,不能用 on
## 二、外连接
### 1、概念
包括左外联接(left join)、右外联接(right join)或完整外部联接
### 2、左连接
(1)左外联接(left join 或 left outer join)的结果集包括左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值(null)。
(2)SQL 语句
```sql
select * from table1 left join table2 on table1.id = table2.id
```
结果
id |
name |
id |
score |
1 |
lee |
1 |
90 |
2 |
zhang |
2 |
100 |
4 |
wang |
NULL |
NULL |
> 注释:包含 table1 的所有行,根据指定条件返回 table2 相应的字段,不符合的以 null 显示
### 3、右连接
(1)右外联接(right join 或 right outer join)是左外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
(2)SQL 语句
```sql
select * from table1 right join table2 on table1.id = table2.id
```
结果
id |
name |
id |
score |
1 |
lee |
1 |
90 |
2 |
zhang |
2 |
100 |
NULL |
NULL |
3 |
70 |
> 注释:包含 table2 的所有行,根据指定条件返回 table1 相应的字段,不符合的以 null 显示
### 4、完整外部联接
(1)完整外部联接(full join 或 full outer join)包含左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。
(2)SQL 语句
```sql
select * from table1 full join table2 on table1.id = table2.id
```
结果
id |
name |
id |
score |
1 |
lee |
1 |
90 |
2 |
zhang |
2 |
100 |
4 |
wang |
NULL |
NULL |
NULL |
NULL |
3 |
70 |
> 注释:返回左右连接的和(见上左、右连接)
## 三、交叉连接(完全)
### 1、概念
没有 where 子句的交叉联接将产生联接所涉及的表的笛卡尔积(cross join 不带条件 where)。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。(table1 和 table2 交叉连接产生 3*3=9 条记录)
### 2、SQL 语句
```sql
select * from table1 cross join table2
```
结果
id |
name |
id |
score |
1 |
lee |
1 |
90 |
2 |
zhang |
1 |
90 |
4 |
wang |
1 |
90 |
1 |
lee |
2 |
100 |
2 |
zhang |
2 |
100 |
4 |
wang |
2 |
100 |
1 |
lee |
3 |
70 |
2 |
zhang |
3 |
70 |
4 |
wang |
3 |
70 |
> 注释:返回 3*3=9 条记录,即笛卡尔积
## 三、多表更新、删除
### 1、多表更新
```sql
--建表table3
create table table3(id int, score int)
insert into table3 select 1, null
insert into table3 select 2, null
insert into table3 select 3, null
```
如表
table3 |
id |
score |
1 |
NULL |
2 |
NULL |
4 |
NULL |
将 table2 中的 score 更新到 table3 中
```sql
update b set b.score = a.score from table2 a, table3 b where a.id = b.id
```
结果
table3 |
id |
score |
1 |
90 |
2 |
100 |
4 |
70 |
### 2、多表删除
```sql
delete a from table1 a left join table2 b on a.id = b.id where b.id is null
--等同于
delete from table1 where not exists(select 1 from table2 b where table1.id = b.id)
```
删除前
table1 |
table2 |
id |
name |
id |
score |
1 |
lee |
1 |
90 |
2 |
zhang |
2 |
100 |
4 |
wang |
3 |
70 |
删除后
table1 |
table2 |
id |
name |
id |
score |
1 |
lee |
1 |
90 |
2 |
zhang |
2 |
100 |
|
|
3 |
70 |
> 注释:将 table2 表中未使用的 table1 表编号删除
```sql
delete a from table1 a, table2 b where a.id = b.id
--等同于
delete from table1 where exists(select 1 from table2 b where table1.id = b.id)
```
结果
table1 |
table2 |
id |
name |
id |
score |
4 |
wang |
1 |
90 |
|
|
2 |
100 |
|
|
3 |
70 |
> 注释:将 table2 表中使用的 table1 表编号删除