数据库篇-mysql详解之多表关系( 二 )

一 : 外键

现在有两个表category分类表

| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| cid   | varchar(32)  | NO   | PRI | NULL    |       |
| cname | varchar(100) | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+

product商品表

+-------------+-------------+------+-----+---------+-------+
| Field       | Type        | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| pid         | varchar(32) | NO   | PRI | NULL    |       |
| pname       | varchar(40) | YES  |     | NULL    |       |
| price       | double      | YES  |     | NULL    |       |
| category_id | varchar(32) | YES  |     | NULL    |       |
+-------------+-------------+------+-----+---------+-------+

其中在product表中的字段category_id存放的是 category表中cid(主键)的信息列称为外键. 此时分类称为主表,'cid'称为主键,product称为从表,category_id称为外键,通过主表的主键和从表的外键来描述主外键关系,呈现就是一对多的关系.

外键的特点 :
  • 从表外键的值是对主表主键的引用.
  • 从表外键类型,必须与主表主键类型一致.
声明外键约束
alter table 从表 add [constraint][外键名称] foreign key (从表字段名) references 主表(主表的主键)

外键名称 用于删除外键约束的,一般建议_fk结尾

alter table 从表 drop foregin key 外键名称

使用外键目的是为了保证数据的完整性,删除的时候会有约束.

对例子进行外键约束

alter table product add foreign key(category_id) references category(cid);

从表不能够添加(更新),主表中不存在的数据.
主表不能够删除(更新),从表中已经使用的数据.

二 : 多表之间的关系

表与表数据之间的关系.

  • 一对多关系 :

产品与产品类别, 一个产品对应一种类别,一个产品类别包含多种产品,举一个例子来说, 《蚁人》只属于漫威系列,《雷神》也只属于漫威系列,但是漫威宇宙还包含很多很多系列电影.

  • 多对多关系 :

大学老师与学生的关系,一个学生可以从不同老师那里学习到知识,相对的一个老师可以教多个学生.

多对多关系建表原则 : 需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键,也就是将一个多对多拆分成两个一对多.

  • 一对一关系:

在实际开发中应用不多,一对一可以用一张表完成.
外键唯一 : 主表的主键和从表的外键( 唯一 ),形成主外键关系,unique
外键是主键 : 主表的主键和从表的主键,形成主外键关系.

三 : 多表查询

建立多对多,订单表商品表

订单表

create table orders(
    oid varchar(32) primary key,
    totalprice double
);

订单项表

create table orderitem(
    oid varchar(50),
    pid varchar(50)
);

联合主键

alter table orderitem add primary key(oid,pid);

订单表和订单项表主外键关系

alter table orderitem add constraint orderitem_orders_fk foreign key(oid) references orders(oid);

商品表和订单项表的主外键关系

alter table orderitem add constraint orderitem_product_fk foreign key(pid) references product(pid);

多对多关系构图

+-------------+-------------+------+-----+---------+-------+
| Field       | Type        | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| pid         | varchar(32) | NO   | PRI | NULL    |       |
| pname       | varchar(40) | YES  |     | NULL    |       |
| price       | double      | YES  |     | NULL    |       |
| category_id | varchar(32) | YES  | MUL | NULL    |       |
+-------------+-------------+------+-----+---------+-------+

1
|
|
|

+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| oid   | varchar(50) | NO   | PRI | NULL    |       |
| pid   | varchar(50) | NO   | PRI | NULL    |       |
+-------+-------------+------+-----+---------+-------+


|
|
|
1

+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| oid        | varchar(32) | NO   | PRI | NULL    |       |
| totalprice | double      | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+

准备数据

+------+-----------------+-------+-------------+
| pid  | pname           | price | category_id |
+------+-----------------+-------+-------------+
| p001 | 苹果笔记本      | 14000 | c001        |
| p002 | 苹果手机        |  9000 | c001        |
| p003 | 手写板          |  5000 | c001        |
| p004 | JACK JONES      |   800 | c002        |
| p005 | 耐克            |   600 | c002        |
| p006 | 阿迪达斯        |   440 | c002        |
| p007 | 李宁            |   200 | c002        |
| p008 | 香奈儿          |   800 | c003        |
| p009 | 兰蔻            |  1000 | c003        |
+------+-----------------+-------+-------------+
+------+-----------+
| cid  | cname     |
+------+-----------+
| c001 | 电子      |
| c002 | 服饰      |
| c003 | 化妆品    |
+------+-----------+
  • 交叉查询

两表之间的乘机,不常用

select * from A,B;
  • 内连查询

隐式内连接

select * from A,B where 条件 ; 
mysql> select * from category,product where cid = category_id;
+------+-----------+------+-----------------+-------+-------------+
| cid  | cname     | pid  | pname           | price | category_id |
+------+-----------+------+-----------------+-------+-------------+
| c001 | 电子      | p001 | 苹果笔记本      | 14000 | c001        |
| c001 | 电子      | p002 | 苹果手机        |  9000 | c001        |
| c001 | 电子      | p003 | 手写板          |  5000 | c001        |
| c002 | 服饰      | p004 | JACK JONES      |   800 | c002        |
| c002 | 服饰      | p005 | 耐克            |   600 | c002        |
| c002 | 服饰      | p006 | 阿迪达斯        |   440 | c002        |
| c002 | 服饰      | p007 | 李宁            |   200 | c002        |
| c003 | 化妆品    | p008 | 香奈儿          |   800 | c003        |
| c003 | 化妆品    | p009 | 兰蔻            |  1000 | c003        |
+------+-----------+------+-----------------+-------+-------------+

显示内连接

select * from A inner join B on 条件;
mysql> select distinct cname from category c inner join product p on c.cid = p.category_id;
+-----------+
| cname     |
+-----------+
| 电子      |
| 服饰      |
| 化妆品    |
+-----------+
  • 外连接查询

我们往 类别表与商品表分别添加两条数据

 insert into category(cname,cid) values('甜品',5);
 insert into product(pid,pname,price,category_id) values('p010','甜筒',14,null);

左外连接 : left outer join

select * from A left outer join B on 条件

右外连接 : right outer join

select * from A right outer join B on 条件
mysql> select * from category c left outer join product p on c.cid = p.category_id;
+------+-----------+------+-----------------+-------+-------------+
| cid  | cname     | pid  | pname           | price | category_id |
+------+-----------+------+-----------------+-------+-------------+
| 5    | 甜品      | NULL | NULL            |  NULL | NULL        |
| c001 | 电子      | p001 | 苹果笔记本      | 14000 | c001        |
| c001 | 电子      | p002 | 苹果手机        |  9000 | c001        |
| c001 | 电子      | p003 | 手写板          |  5000 | c001        |
| c002 | 服饰      | p004 | JACK JONES      |   800 | c002        |
| c002 | 服饰      | p005 | 耐克            |   600 | c002        |
| c002 | 服饰      | p006 | 阿迪达斯        |   440 | c002        |
| c002 | 服饰      | p007 | 李宁            |   200 | c002        |
| c003 | 化妆品    | p008 | 香奈儿          |   800 | c003        |
| c003 | 化妆品    | p009 | 兰蔻            |  1000 | c003        |
+------+-----------+------+-----------------+-------+-------------+
10 rows in set (0.00 sec)
mysql> select * from category c right outer join product p on c.cid = p.category_id;
+------+-----------+------+-----------------+-------+-------------+
| cid  | cname     | pid  | pname           | price | category_id |
+------+-----------+------+-----------------+-------+-------------+
| c001 | 电子      | p001 | 苹果笔记本      | 14000 | c001        |
| c001 | 电子      | p002 | 苹果手机        |  9000 | c001        |
| c001 | 电子      | p003 | 手写板          |  5000 | c001        |
| c002 | 服饰      | p004 | JACK JONES      |   800 | c002        |
| c002 | 服饰      | p005 | 耐克            |   600 | c002        |
| c002 | 服饰      | p006 | 阿迪达斯        |   440 | c002        |
| c002 | 服饰      | p007 | 李宁            |   200 | c002        |
| c003 | 化妆品    | p008 | 香奈儿          |   800 | c003        |
| c003 | 化妆品    | p009 | 兰蔻            |  1000 | c003        |
| NULL | NULL      | p010 | 甜筒            |    14 | NULL        |
+------+-----------+------+-----------------+-------+-------------+

注意观察上面左连接与右连接的查询结果分析其联系.
内连接 : 查询两个表交集
左外连接 : 左表全部以及两个表的交集
右外连接 : 右表全部以及两个表的交集

四 : 子查询

一条select语句结果作为另一条语句的一部分(查询条件,查询结果,表等).

mysql> select * from product where category_id = (select cid from category where cname = '电子');
+------+-----------------+-------+-------------+
| pid  | pname           | price | category_id |
+------+-----------------+-------+-------------+
| p001 | 苹果笔记本      | 14000 | c001        |
| p002 | 苹果手机        |  9000 | c001        |
| p003 | 手写板          |  5000 | c001        |
+------+-----------------+-------+-------------+
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容