一、关系表
假如有一个包含产品目录的数据库表,其中每种类别的物品占一行。 对于每种物品要存储的信息包括产品描述和价格,以及生产该产品的供 应商信息。现在,假如有由同一供应商生产的多种物品,那么在何处存储供应 商信息(如,供应商名、地址、联系方法等)呢?将这些数据与产品信 息分开存储的理由如下。
- 因为同一供应商生产的每个产品的供应商信息都是相同的,对每 个产品重复此信息既浪费时间又浪费存储空间。
- 如果供应商信息改变(例如,供应商搬家或电话号码变动),只需 改动一次即可。
- 如果有重复数据(即每种产品都存储供应商信息),很难保证每次 输入该数据的方式都相同。不一致的数据在报表中很难利用。
关键是,相同数据出现多次决不是一件好事,此因素是关系数据库 设计的基础。关系表的设计就是要保证把信息分解成多个表,一类数据 一个表。各表通过某些常用的值(即关系设计中的关系(relational))互 相关联。
在这个例子中,可建立两个表,一个存储供应商信息,另一个存储 产品信息。vendors表包含所有供应商信息,每个供应商占一行,每个供 应商具有唯一的标识。此标识称为主键(primary key),可以是供应商ID或任何其他唯一值。
products表只存储产品信息,它除了存储供应商ID(vendors表的主 键)外不存储其他供应商信息。vendors表的主键又叫作products的外键, 它将vendors表与products表关联,利用供应商ID能从vendors表中找出 相应供应商的详细信息。外键(foreignkey)
外键为某个表中的一列,它包含另一个表 的主键值,定义了两个表之间的关系。
这样做的好处如下:
- 供应商信息不重复,从而不浪费时间和空间;
- 如果供应商信息变动,可以只更新vendors表中的单个记录,相关表中的数据不用改动;
- 由于数据无重复,显然数据是一致的,这使得处理数据更简单。
总之,关系数据可以有效地存储和方便地处理。因此,关系数据库 的可伸缩性远比非关系数据库要好。
可伸缩性(scale) 能够适应不断增加的工作量而不失败。设 计良好的数据库或应用程序称之为可伸缩性好 ——《Mysql必知必会》
二、创建联结
方法:规定要联结的所有表,以及他们之间如何来联结
只需要通过一条select语句就可以把存储在多个表中的数据检索出来
例子:查看所有员工的职业,部门和薪资
mysql> select ename,job ,dname ,sal
from emp,dept
where emp.deptno = dept.deptno order by job;
+--------+-----------+------------+---------+
| ename | job | dname | sal |
+--------+-----------+------------+---------+
| SCOTT | ANALYST | RESEARCH | 3000.00 |
| FORD | ANALYST | RESEARCH | 3000.00 |
| SMITH | CLERK | RESEARCH | 800.00 |
| ADAMS | CLERK | RESEARCH | 1100.00 |
| JAMES | CLERK | SALES | 950.00 |
| MILLER | CLERK | ACCOUNTING | 1300.00 |
| JONES | MANAGER | RESEARCH | 2975.00 |
| BLAKE | MANAGER | SALES | 2850.00 |
| CLARK | MANAGER | ACCOUNTING | 2450.00 |
| KING | PRESIDENT | ACCOUNTING | 5000.00 |
| ALLEN | SALESMAN | SALES | 1600.00 |
| WARD | SALESMAN | SALES | 1250.00 |
| MARTIN | SALESMAN | SALES | 1250.00 |
| TURNER | SALESMAN | SALES | 1500.00 |
+--------+-----------+------------+---------+
14 rows in set (0.00 sec)
分析:
FROM子句:
- 这里的from子句指出了要联结的所有表的名称。
WHERE子句:
- where指出了联结规则
三、联结表时WHERE子句不能丢
到这里我们明白多个表之间的联结是同通过WHERE子句的联结规则来连接的,但是这种链接规则是在SELECT语句执行过程中才连接的,并不是在创建表的的时候就强调他们之间有这种关系,而是必须通过WHERE子句来表达你想达到的目的。
当然了,丢掉这个where子句在sql语法上并没有毛病,但是没有按照约束规则来达成你逻辑上某些列的匹配。
笛卡尔积:
由于没有通过where子句来规定联结关系,那么返回结果将是一个笛卡尔积数目的表。
返
回
表
总
行
数
=
表
1
行
数
×
表
2
行
数
×
表
3
行
数
×
.
.
.
×
表
n
行
数
返回表总行数 = 表1行数 × 表2行数 ×表3行数×...×表n行数
返回表总行数=表1行数×表2行数×表3行数×...×表n行数
mysql> select ename,job ,dname ,sal
from emp,dept
order by ename;
+--------+-----------+------------+---------+
| ename | job | dname | sal |
+--------+-----------+------------+---------+
| ADAMS | CLERK | OPERATIONS | 1100.00 |
| ADAMS | CLERK | SALES | 1100.00 |
| ADAMS | CLERK | RESEARCH | 1100.00 |
| ADAMS | CLERK | ACCOUNTING | 1100.00 |
| ALLEN | SALESMAN | OPERATIONS | 1600.00 |
| ALLEN | SALESMAN | SALES | 1600.00 |
| ALLEN | SALESMAN | RESEARCH | 1600.00 |
| ALLEN | SALESMAN | ACCOUNTING | 1600.00 |
| BLAKE | MANAGER | OPERATIONS | 2850.00 |
| BLAKE | MANAGER | ACCOUNTING | 2850.00 |
| BLAKE | MANAGER | RESEARCH | 2850.00 |
| BLAKE | MANAGER | SALES | 2850.00 |
| CLARK | MANAGER | ACCOUNTING | 2450.00 |
| CLARK | MANAGER | RESEARCH | 2450.00 |
| CLARK | MANAGER | SALES | 2450.00 |
| CLARK | MANAGER | OPERATIONS | 2450.00 |
| FORD | ANALYST | OPERATIONS | 3000.00 |
| FORD | ANALYST | SALES | 3000.00 |
| FORD | ANALYST | RESEARCH | 3000.00 |
| FORD | ANALYST | ACCOUNTING | 3000.00 |
| JAMES | CLERK | OPERATIONS | 950.00 |
| JAMES | CLERK | SALES | 950.00 |
| JAMES | CLERK | RESEARCH | 950.00 |
| JAMES | CLERK | ACCOUNTING | 950.00 |
| JONES | MANAGER | SALES | 2975.00 |
| JONES | MANAGER | ACCOUNTING | 2975.00 |
| JONES | MANAGER | RESEARCH | 2975.00 |
| JONES | MANAGER | OPERATIONS | 2975.00 |
| KING | PRESIDENT | OPERATIONS | 5000.00 |
| KING | PRESIDENT | SALES | 5000.00 |
| KING | PRESIDENT | RESEARCH | 5000.00 |
| KING | PRESIDENT | ACCOUNTING | 5000.00 |
| MARTIN | SALESMAN | ACCOUNTING | 1250.00 |
| MARTIN | SALESMAN | RESEARCH | 1250.00 |
| MARTIN | SALESMAN | SALES | 1250.00 |
| MARTIN | SALESMAN | OPERATIONS | 1250.00 |
| MILLER | CLERK | OPERATIONS | 1300.00 |
| MILLER | CLERK | SALES | 1300.00 |
| MILLER | CLERK | RESEARCH | 1300.00 |
| MILLER | CLERK | ACCOUNTING | 1300.00 |
| SCOTT | ANALYST | OPERATIONS | 3000.00 |
| SCOTT | ANALYST | ACCOUNTING | 3000.00 |
| SCOTT | ANALYST | RESEARCH | 3000.00 |
| SCOTT | ANALYST | SALES | 3000.00 |
| SMITH | CLERK | OPERATIONS | 800.00 |
| SMITH | CLERK | ACCOUNTING | 800.00 |
| SMITH | CLERK | RESEARCH | 800.00 |
| SMITH | CLERK | SALES | 800.00 |
| TURNER | SALESMAN | ACCOUNTING | 1500.00 |
| TURNER | SALESMAN | RESEARCH | 1500.00 |
| TURNER | SALESMAN | SALES | 1500.00 |
| TURNER | SALESMAN | OPERATIONS | 1500.00 |
| WARD | SALESMAN | ACCOUNTING | 1250.00 |
| WARD | SALESMAN | RESEARCH | 1250.00 |
| WARD | SALESMAN | SALES | 1250.00 |
| WARD | SALESMAN | OPERATIONS | 1250.00 |
+--------+-----------+------------+---------+
56 rows in set (0.00 sec
四、内部联结
等值联结
基于两个表之间的相等测试
内部联结
内部联结定义和等值联结定义差不多。
内部联结的新语法(INNER JOIN …ON…)
mysql> select ename,job ,dname ,sal
from emp
inner join dept
on emp.deptno = dept.deptno;
+--------+-----------+------------+---------+
| ename | job | dname | sal |
+--------+-----------+------------+---------+
| SMITH | CLERK | RESEARCH | 800.00 |
| ALLEN | SALESMAN | SALES | 1600.00 |
| WARD | SALESMAN | SALES | 1250.00 |
| JONES | MANAGER | RESEARCH | 2975.00 |
| MARTIN | SALESMAN | SALES | 1250.00 |
| BLAKE | MANAGER | SALES | 2850.00 |
| CLARK | MANAGER | ACCOUNTING | 2450.00 |
| SCOTT | ANALYST | RESEARCH | 3000.00 |
| KING | PRESIDENT | ACCOUNTING | 5000.00 |
| TURNER | SALESMAN | SALES | 1500.00 |
| ADAMS | CLERK | RESEARCH | 1100.00 |
| JAMES | CLERK | SALES | 950.00 |
| FORD | ANALYST | RESEARCH | 3000.00 |
| MILLER | CLERK | ACCOUNTING | 1300.00 |
+--------+-----------+------------+---------+
14 rows in set (0.00 sec)
分析:
- FROM子句:
两个表之间的关系时FROM子句的组成部分,用INNNER JOIN指定
- ON子句:
两个表之间的联结规则由ON子句指定
ANSI SQL规范首选INNER JOIN语法
五、性能考虑
MySQL在运行时关联指定的每个表以处理联结。 这种处理可能是非常耗费资源的,因此应该仔细,不要联结 不必要的表。联结的表越多,性能下降越厉害。
子查询和联结查询
假设现在我们要查询所有在 NEW YORK 和 CHICAGO工作的员工,但是
员工的工作地址信息存储在部门表中,员工具体姓名存在员工表中。
子查询:
mysql> select ename ,deptno
from emp
where deptno in (select
deptno
from dept
where loc in ('NEW YORK','CHICAGO'));
+--------+--------+
| ename | deptno |
+--------+--------+
| ALLEN | 30 |
| WARD | 30 |
| MARTIN | 30 |
| BLAKE | 30 |
| CLARK | 10 |
| KING | 10 |
| TURNER | 30 |
| JAMES | 30 |
| MILLER | 10 |
+--------+--------+
9 rows in set (0.00 sec)
联结查询:
mysql> select ename, emp.deptno ,loc
from emp inner
join dept
on emp.deptno = dept.deptno ;
+--------+--------+----------+
| ename | deptno | loc |
+--------+--------+----------+
| SMITH | 20 | DALLAS |
| ALLEN | 30 | CHICAGO |
| WARD | 30 | CHICAGO |
| JONES | 20 | DALLAS |
| MARTIN | 30 | CHICAGO |
| BLAKE | 30 | CHICAGO |
| CLARK | 10 | NEW YORK |
| SCOTT | 20 | DALLAS |
| KING | 10 | NEW YORK |
| TURNER | 30 | CHICAGO |
| ADAMS | 20 | DALLAS |
| JAMES | 30 | CHICAGO |
| FORD | 20 | DALLAS |
| MILLER | 10 | NEW YORK |
+--------+--------+----------+
14 rows in set (0.00 sec)
注意:
select 主句后的列名如果在多个表中出现多义性时候必须使用完全限定名(前面加上所在表明,如emp.deptno),否则会报字段模糊错误。
mysql> select ename, deptno , loc from emp inner join dept on emp.deptno = dept.deptno;
ERROR 1052 (23000): Column 'deptno' in field list is ambiguous
六、使用表别名
别名除了可用于被检索的列名和可计算字段以外,同样可以用于表名的别名。
优点:
- 缩短SQL语句
- 允许在一条SQL语句中多次使用相同的表
示例:
mysql> select ename ,em.deptno ,loc
from emp as em , dept as de
where em.deptno =
de.deptno;
+--------+--------+----------+
| ename | deptno | loc |
+--------+--------+----------+
| SMITH | 20 | DALLAS |
| ALLEN | 30 | CHICAGO |
| WARD | 30 | CHICAGO |
| JONES | 20 | DALLAS |
| MARTIN | 30 | CHICAGO |
| BLAKE | 30 | CHICAGO |
| CLARK | 10 | NEW YORK |
| SCOTT | 20 | DALLAS |
| KING | 10 | NEW YORK |
| TURNER | 30 | CHICAGO |
| ADAMS | 20 | DALLAS |
| JAMES | 30 | CHICAGO |
| FORD | 20 | DALLAS |
| MILLER | 10 | NEW YORK |
+--------+--------+----------+
14 rows in set (0.00 sec)
mysql> select ename, emp.deptno ,loc
from emp
inner join dept as de
on emp.deptno = de.deptno ;
+--------+--------+----------+
| ename | deptno | loc |
+--------+--------+----------+
| SMITH | 20 | DALLAS |
| ALLEN | 30 | CHICAGO |
| WARD | 30 | CHICAGO |
| JONES | 20 | DALLAS |
| MARTIN | 30 | CHICAGO |
| BLAKE | 30 | CHICAGO |
| CLARK | 10 | NEW YORK |
| SCOTT | 20 | DALLAS |
| KING | 10 | NEW YORK |
| TURNER | 30 | CHICAGO |
| ADAMS | 20 | DALLAS |
| JAMES | 30 | CHICAGO |
| FORD | 20 | DALLAS |
| MILLER | 10 | NEW YORK |
+--------+--------+----------+
14 rows in set (0.00 sec)