数据库(四)

137 阅读5分钟

数据库(四)

子查询的分类:

相关子查询

在外查询中,每查询一条记录,需要重新做一次子查询,这种称为相关子查询。相关子查询的执行依赖于外部查询的数据,外部查询返回一次,子查询就执行一次。所以,相关子查询效率很低

-- 有些国家的人口数比她的周边国家要多三倍,请列出这些国家和地区。 

SELECT * FROM bbc b1 WHERE population >4*(SELECT MAX(population) FROM bbc b2 WHERE b1.`region`=b2.`region` AND b1.`contryName`!=b2.`contryName`);

非相关子查询

在主查询中,子查询只需要执行一次,子查询结果不再变化。子查询结果供主查询使用,这种查询方式称为非相关子查询。

-- 显示欧州人口总数和总GDP 

SELECT SUM(population),SUM(gdp) FROM bbc WHERE region='Europe';
区分:

是相关子查询,还是非相关子查询。主要看子查询是否能单独运行,子查询是否依赖外查询的查询结果

如果子查询需要依赖外查询的查询结果,不能单独运行,就是相关子查询;

如果子查询不需要依赖外查询的查询结果,可以单独运行,就是非相关子查询。

数据完整性

数据完整性 = 数据准确性 + 数据可靠性

为了防止垃圾数据的产生,从而影响数据库的执行效率。

分类:

数据完整性分为:实体完整性、域完整性、引用完整性、自定义完整性

实体完整性

保证每行所代表的实体能相互区别,不能存在两条一模一样的记录。

实现方法:

1、主键约束 :主键(Primary Key)是表中的一到多个列,主键不能为空,也不能重复。一个表中只能有一个主键。

适合做主键的列,需要满足四个条件

1、值必须唯一

2、值不能为空

3、不能带业务含义

4、值不能变化

注:身份证不适合做主键。身份证中国人才有,外国人没有(值不能为空);身份证具有业务含义;身份证可能会发生变动(一代身份证、二代身份证)。

2、唯一约束:指给定列的所有值必须唯一,该列在表中每一行的值必须唯一。它和主键约束的区别在于该列可以为空,并且可以在一张表中给出多个列设置唯一约束。

CREATE TABLE 表名(

……

phone VARCHAR(20) **UNIQUE****unique:设置唯一性**
域完整性

保证指定列是数据是有效性(mysql 对域完整性支持不好)。

实现方式:

1、非空约束(not null) :指定列的值,不能为null值。

2、默认值(default) :添加记录时,如果该列的值不做插入,那么以默认值插入。

3、检查约束(check) :检查插入列数据的有效性。(mysql不支持)

  CREATE TABLE t_em( 
  pk_emld INT PRIMARY KEY AUTO_INCREMENT, 
  e_name VARCHAR(20) NOT NULL, -- 非空约束 
  e_status ENUM('在职','离职') DEFAULT '在职', -- 默认值 
  e_money INT CHECK(e_money>1000 AND e_money<10000) -- 检查约束 );
引用完整性

从表外键中出现的数据,必须在主表的主键列中出现。

实现方式:

外键约束

外键和外键约束:

外键是描述表与表之间联系的一个列,是表中的列;

外键约束是指在外键列上加上一个约束,强制外键列引用的数据是正确的。如果违反该约束,则不允许该条数据的修改或插入。

注意:没有外键约束,不代表没有外键。

-- 添加外键约束 

ALTER TABLE t_car ADD CONSTRAINT fk_1 FOREIGN KEY(fk_manId) REFERENCES t_man(pk_manId);
删除主表记录:

删除主表记录时,如果该主表记录有从表记录引用。由于有外键约束存在,则无法删除主表记录。

删除主表记录有三种方式

1、级联删除:先将主表记录中关联的从表记录全部删除,然后再删除主表记录。

DELETE FROM t_car WHERE fk_manId=1; DELETE FROM t_man WHERE Pk_manId=1;

2、外键置空:先将主表记录中关联的从表记录外键设置为null,然后再删除主表记录。

UPDATE t_car SET fk_manId=NULL WHERE fk_manId=2; DELETE FROM t_man WHERE pk_manId=2;

3、改变状态:将主表记录添加标识列(有效/无效);删除主表记录时,将状态修改为无效。

联表查询:

如果数据来自多个表,那么可以采用联表查询的方式来实现。

表联接就是指将多个表联合在一起实现查询效果。

笛卡尔乘积:

是将两张表的所有数据相连,最后联接的结果数为两张表数量的乘积。

-- 查询所有汽车,以及汽车的主人名字 

SELECT c.*,m.m_name FROM t_man m **JOIN** t_car c **ON** **m.pk_manId=c.fk_manId**;

SELECT c.*,m.m_name FROM t_man m,t_car c WHERE m.pk_manId=c.fk_manId;

表联接分类:

內联接、外联接、自联接

內联接

只能查询两个表之间有关联记录的数据。

-- 显示所有的公民,以及公民拥有的汽车数量 

SELECT m.m_name,COUNT(c.pk_carId) FROM t_man m **JOIN** t_car c **ON** m.pk_manId=c.fk_manId **GROUP BY m.pk_manId**; 

SELECT m.m_name,COUNT(c.pk_carId) FROM t_man m **,** t_car c **WHERE** m.pk_manId=c.fk_manId GROUP BY m.pk_manId;

如果有汽车没有主人,则不在查询结果中。內联接只能查询有主人的汽车。

外联接

可以查询出一个表中,所有符合条件的记录,无论该记录是否有关联数据。

-- 显示所有的公民,以及公民拥有的汽车数量

SELECT m.m_name,COUNT(c.pk_carId) FROM t_man m **LEFT** JOIN t_car c ON m.pk_manId=c.fk_manId GROUP BY m.pk_manId;
自联接

将自己的表与自己联接。

-- 列出所有的员工和员工的领导人 

SELECT w2.`w_name`,w1.`w_name` FROM t_worker w1 RIGHT JOIN t_worker w2 ON w1.`pk_workerId`=w2.`fk_leader`;

视图:

视图可以看做是SQL语句的封装,可以看做是临时表,视图查询的结果会随着真实表数据的变化而变化。视图只提供查询功能,不提供数据修改的功能

-- 列出所有政党和每个政党议员人数 

**CREATE VIEW** v_partyNum **AS** SELECT p.`partyName`,COUNT(m.`mspName`) num FROM party p LEFT JOIN msp m ON p.`partyCode`=m.`party` GROUP BY p.`partyCode`;

SELECT * FROM v_partyNum;

数据库三范式

第一范式

一范式:行不重复(每条记录不能完全一样),列不可再分(一条记录的列只能有一个值)。

第二范式

二范式:非主依主。非主键列必须依赖于主键列。二范式要求一个表只描述一个实体。

第三范式

三范式:非主独立。非主键列之间不能有依赖关系。