mysql中的第三范式
※多表操作 (凡是多表,都要用到关联技术(把多表合并成一个新表): 左关联、右关联、内关联。还有一个外(全)关联,MySQL不支持,为考虑软件兼容,我们开发一般不用。)
※表与表之间的关系:1对1,1对多,多对多
一、1对1
※第三范式: 1方建主表(id为主键字段), 多方建外键字段(husband--参考主表的主键id,加unique)
CREATE TABLE man(
id VARCHAR(32) PRIMARY KEY,
NAME VARCHAR(30)
);
CREATE TABLE woman(
id VARCHAR(32) PRIMARY KEY,
NAME VARCHAR(30),
husband VARCHAR(32) UNIQUE,
CONSTRAINT wm_fk FOREIGN KEY(husband) REFERENCES man(id)
);
//DROP TABLE woman;
INSERT INTO man VALUES('1','张三');
INSERT INTO man VALUES('2','李四');
INSERT INTO man VALUES('3','王五');
INSERT INTO woman VALUES('1','小花','1');
INSERT INTO woman VALUES('2','玉芬','3');
INSERT INTO woman VALUES('3','小玉','1');//Error:违反1对1
INSERT INTO woman VALUES('3','小玉','10');//Error:违反外键--主表必须存在该外键值
INSERT INTO man VALUES('10','王六');
INSERT INTO woman VALUES('3','小玉','10');//OK
//◇查询夫妻信息(内联)
SELECT man.name AS 丈夫, woman.name AS 妻子 FROM man
INNER JOIN woman ON man.id=woman.husband;
SELECT m.name AS 丈夫, w.name AS 妻子 FROM man AS m
INNER JOIN woman AS w ON m.id=w.husband;
二、1对多
※第三范式: 1方建主表(id为主键字段), 多方建外键字段(pid--参考主表的主键id,不加unique)
CREATE TABLE person2(
id VARCHAR(32) PRIMARY KEY,
NAME VARCHAR(30),
sex CHAR(1)
);
DROP TABLE car2;
CREATE TABLE car(
id VARCHAR(32) PRIMARY KEY,
NAME VARCHAR(30),
price NUMERIC(10,2),
pid VARCHAR(32),
CONSTRAINT car_fk FOREIGN KEY(pid) REFERENCES person2(id)
);
INSERT INTO person2 VALUES('P01','Jack','1');
INSERT INTO person2 VALUES('P02','Tom','1');
INSERT INTO person2 VALUES('P03','Rose','0');
INSERT INTO car VALUES('C001','BMW',30,'P01');
INSERT INTO car VALUES('C002','BEnZ',40,'P01');
INSERT INTO car VALUES('C003','Audi',40,'P01');
INSERT INTO car VALUES('C004','QQ',5.5,'P02');
//外键字段值可以为“NULL”
INSERT INTO car(id,NAME,price) VALUES('C005','ABC',10);
INSERT INTO car(id,NAME,price) VALUES('C006','BCD',10);
//◇查询哪些人有哪些车
SELECT * FROM car INNER JOIN person2 ON car.pid=person2.id;
SELECT car.NAME,car.price,person2.name FROM car
INNER JOIN person2 ON car.pid=person2.id ;
//◇查询Jack有哪些车
SELECT car.NAME,car.price,person2.name FROM car
INNER JOIN person2 ON car.pid=person2.id where person2.name='Jack';
//◇查询哪些人有两辆或两辆以上的车
//失败品:--每组只显示第一条
SELECT car.NAME,car.price,person2.name FROM car
INNER JOIN person2 ON car.pid=person2.id GROUP BY person2.id HAVING COUNT(car.pid)>=2;
//过渡版
SELECT car.NAME,car.price,person2.name FROM car
INNER JOIN person2 ON car.pid=person2.id WHERE person2.id IN('P01','P02');
SELECT pid FROM car GROUP BY pid HAVING COUNT(pid)>=2; //把上面写死的pid写成活的
//OK版
SELECT car.NAME,car.price,person2.name FROM car
INNER JOIN person2 ON car.pid=person2.id WHERE person2.id IN(
SELECT pid FROM car GROUP BY pid HAVING COUNT(pid)>=2
);
//演示左关联: SELECT * FROM person2 LEFT JOIN car ON car.pid=person2.id;
//◇查询哪些人没有车
SELECT person2.name FROM person2 LEFT JOIN car ON car.pid=person2.id
WHERE car.id IS NULL;
//◇补一个外键的概念(默认是约束): 删除主键信息时,当该主键字段值在外键表中存在时,该记录是不能删除的。---要把外键表是的相关信息删除之后,才能删除。 ---更新同理
DELETE FROM person2 WHERE id='P01';//car表中存在pid='P01'的车,所以主表不能删除'P01'这条记录
三、多对多( 3个表= 2个实体表 + 1个关系表 )
※第三范式: 两个实体都建成独立的主表, 另外再单独建一个关系表(采用联合主键)
1、分别建议两个实体表(没有外键,但有自己的主键, 没有冗余信息)
//DROP TABLE stud;
//学生表
CREATE TABLE stud(
id VARCHAR(32) PRIMARY KEY,
NAME VARCHAR(30)
);
//课程表
CREATE TABLE ject(
id VARCHAR(32) PRIMARY KEY,
NAME VARCHAR(30)
);
2、另外补建一个关系表
CREATE TABLE sj(
studid VARCHAR(32) NOT NULL,
jectid VARCHAR(32)
);
//注意,要先建联合主键,再添加外键。顺序不能反了。
ALTER TABLE sj ADD CONSTRAINT sj_pk PRIMARY KEY(studid,jectid);
ALTER TABLE sj ADD CONSTRAINT sj_fk1 FOREIGN KEY(studid) REFERENCES stud(id);
ALTER TABLE sj ADD CONSTRAINT sj_fk2 FOREIGN KEY(jectid) REFERENCES ject(id);
//删除外键约束
//ALTER TABLE sj DROP FOREIGN KEY sj_fk1;
//ALTER TABLE sj DROP FOREIGN KEY sj_fk2;
3、添加一些演示数据
//实体表1
INSERT INTO stud VALUES('S001','Jack');
INSERT INTO stud VALUES('S002','Rose');
INSERT INTO stud VALUES('S003','Tom');
//实体表2
INSERT INTO ject VALUES('J001','Java');
INSERT INTO ject VALUES('J002','Oracle');
INSERT INTO ject VALUES('J003','XML');
INSERT INTO ject VALUES('J004','JSP');
INSERT INTO ject VALUES('J005','Game');
//关系表
INSERT INTO sj VALUES('S001','J001');
INSERT INTO sj VALUES('S001','J003');
INSERT INTO sj VALUES('S001','J004');
INSERT INTO sj VALUES('S002','J002');
INSERT INTO sj VALUES('S002','J003');
INSERT INTO sj VALUES('S002','J004');
//查询哪些人选了哪些课
//SQL组织的1992标准,可用,但效率不高
SELECT stud.name, ject.NAME FROM stud,ject,sj WHERE stud.id=sj.studid AND ject.id=sj.jectid;
//SQL组织的1996标准,效率高,推荐使用---关联
SELECT stud.name, ject.NAME FROM stud INNER JOIN sj ON stud.id=sj.studid
INNER JOIN ject ON ject.id=sj.jectid;
//查询哪些人没选课
SELECT stud.name FROM stud LEFT JOIN sj ON stud.id=sj.studid
LEFT JOIN ject ON ject.id=sj.jectid where ject.id is NULL;
//查询哪些课没人选
SELECT ject.name FROM stud RIGHT JOIN sj ON stud.id=sj.studid
RIGHT JOIN ject ON ject.id=sj.jectid where stud.id is NULL;
--------------------------------------------------------------------------------------------
//额外补充:
1)在java中如果要对mysql进行操作时要导入mysql的jar包,倒入之后点右键中的bulid path进行导包;
2)外键可以保证两个表数据的一致性
mysql中的第三范式的更多相关文章
- 一、MySQL中的索引 二、MySQL中的函数 三、MySQL数据库的备份和恢复 四、数据库设计和优化(重点)
一.MySQL中的索引###<1>索引的概念 索引就是一种数据结构(高效获取数据),在mysql中以文件的方式存在.存储建立了索引列的地址或者指向. 文件 :(以某种数据 结构存放) 存放 ...
- MySQL中You can't specify target table for update in FROM clause一场
mysql中You can't specify target table <tbl> for update in FROM clause错误的意思是说,不能先select出同一表中的某些值 ...
- MySql中in和exists效率
mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop循环,每次loop循环再对内表进行查询.一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的 ...
- [原创]MYSQL中利用外键实现级联删除和更新
MySQL中利用外键实现级联删除.更新 MySQL支持外键的存储引擎只有InnoDB,在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引.在创建索引的时候,可以指定 ...
- mysql中的多行查询结果合并成一个
SELECT GROUP_CONCAT(md.data1) FROM DATA md,contacts cc WHERE md.conskey=cc.id AND md.mimetype_id= 5 ...
- 【转】MySql中的函数
原文:http://www.cnblogs.com/kissdodog/p/4168721.html MySQL数据库提供了很多函数包括: 数学函数: 字符串函数: 日期和时间函数: 条件判断函数: ...
- sqlserver 中数据导入到mysql中的方法以及注意事项
数据导入从sql server 到mysql (将数据以文本格式从sqlserver中导出,注意编码格式,再将文本文件导入mysql中): 1.若从slqserver中导出的表中不包含中文采用: bc ...
- MySQL中有关TIMESTAMP和DATETIME的总结
一.MySQL中如何表示当前时间? 其实,表达方式还是蛮多的,汇总如下: CURRENT_TIMESTAMP CURRENT_TIMESTAMP() NOW() LOCALTIME LOCALTIME ...
- MySQL中索引和优化的用法总结
1.什么是数据库中的索引?索引有什么作用? 引入索引的目的是为了加快查询速度.如果数据量很大,大的查询要从硬盘加载数据到内存当中. 2.InnoDB中的索引原理是怎么样的? InnoDB是Mysql的 ...
随机推荐
- C#中数据类型的安全转换(is,as)
原文 C#中数据类型的安全转换(is,as) 下面代码中,不能装箱,在强制类型转换时出错,因为之前 c 是 class 类型,而却要把它转换为 int 类型,这是不可以的.虽然编译器能通过编译,但是 ...
- asp.net文本编辑器(FCKeditor)
FCKeditor介绍 FCKeditor是一个功能强大支持所见即所得功能的文本编辑器,可以为用户提供微软office软件一样的在线文档编辑服务.它不需要安装任何形式的客户端,兼容绝大多数主流浏览器, ...
- 深入浅出 JavaScript 数组 v0.5
有一段时间不更新博客了,今天分享给大家的是一篇关于JS数组的,数组其实比较简单,但是用法非常灵活,在工作学习中应该多学,多用,这样才能领会数组的真谛. 以下知识主要参考<JS 精粹>和&l ...
- Discuz资料整理
1.截取字符串:messagecutstr(strip_tags($post['message']), 160);
- HW7.8
import java.util.ArrayList; import java.util.Scanner; public class Solution { public static void mai ...
- A Tour of Go Range continued
You can skip the index or value by assigning to _. If you only want the index, drop the ", valu ...
- python 使用__future__
Python的每个新版本都会增加一些新的功能,或者对原来的功能作一些改动.有些改动是不兼容旧版本的,也就是在当前版本运行正常的代码,到下一个版本运行就可能不正常了. 从Python 2.7到Pytho ...
- 【PAT Advanced Level】1004. Counting Leaves (30)
利用广度优先搜索,找出每层的叶子节点的个数. #include <iostream> #include <vector> #include <queue> #inc ...
- SQL中EXISTS的用法和效率
比如在Northwind数据库中有一个查询为SELECT c.CustomerId,CompanyName FROM Customers cWHERE EXISTS(SELECT OrderID FR ...
- 修复bug的流年
工作的过程中,总是会遇到莫名其妙的错误.bug,由于记忆力有限,用一篇文章记录所遇到的bug及解决过程,解决的过程总是痛苦与欢乐.还有一丝丝的无奈,或许这才是真实的生活. 在VS的项目属性" ...