MySQL笔记(二)

本文详细解析了数据库中的多表联查技术,包括笛卡尔积、内连接、左外连接、右外连接等概念,以及外键约束的使用方法,包括创建、动态删除、添加外键及外键约束的参照操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多表联查

多表查询,也叫链接查询

数据环境

SHOW CREATE TABLE `emp`;
| emp   | CREATE TABLE `emp` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(20) NOT NULL COMMENT '用户名',
  `age` tinyint(3) unsigned NOT NULL DEFAULT '18' COMMENT '年龄',
  `sex` enum('男','女','保密') NOT NULL DEFAULT '保密' COMMENT '性别',
  `addr` varchar(20) NOT NULL DEFAULT '北京',
  `dep_id` tinyint(3) unsigned NOT NULL COMMENT '部门对应编号',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8                |
SHOW CREATE TABLE `dep`;
| dep   | CREATE TABLE `dep` (
  `id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
  `dep_name` varchar(50) NOT NULL,
  `dep_desc` varchar(100) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `dep_name` (`dep_name`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 |

SELECT * FROM emp;
+----+----------+-----+--------+--------+--------+
| id | username | age | sex    | addr   | dep_id |
+----+----------+-----+--------+--------+--------+
|  1 | tom      |  20 | 保密   | 北京   |      1 |
|  2 | john     |  23 | 保密   | 北京   |      2 |
|  3 | mike     |  20 | 保密   | 北京   |      3 |
|  4 | rose     |  23 | 保密   | 北京   |      2 |
|  5 | lili     |  20 | 保密   | 北京   |      4 |
|  6 | oven     |  23 | 保密   | 北京   |      1 |
+----+----------+-----+--------+--------+--------+

SELECT * FROM dep;
+----+-----------+--------------+
| id | dep_name  | dep_desc     |
+----+-----------+--------------+
|  1 | 技术部    | 研发         |
|  2 | 人事部    | 人事工作     |
|  3 | 财务部    | 财务工作     |
|  4 | 运营部    | 运营工作     |
+----+-----------+--------------+

-- 需求:查询 emp中的id,username,age dep表中的dep_name
复制代码

笛卡尔积的形式

-- 笛卡尔积的形式相当于两张表乘积
SELECT emp.id,emp.username,emp.age,dep.dep_name FROM emp,dep;

+----+----------+-----+-----------+
| id | username | age | dep_name  |
+----+----------+-----+-----------+
|  1 | tom      |  20 | 人事部    |
|  1 | tom      |  20 | 技术部    |
|  1 | tom      |  20 | 财务部    |
|  1 | tom      |  20 | 运营部    |
|  2 | john     |  23 | 人事部    |
|  2 | john     |  23 | 技术部    |
|  2 | john     |  23 | 财务部    |
|  2 | john     |  23 | 运营部    |
|  3 | mike     |  20 | 人事部    |
|  3 | mike     |  20 | 技术部    |
|  3 | mike     |  20 | 财务部    |
|  3 | mike     |  20 | 运营部    |
|  4 | rose     |  23 | 人事部    |
|  4 | rose     |  23 | 技术部    |
|  4 | rose     |  23 | 财务部    |
|  4 | rose     |  23 | 运营部    |
|  5 | lili     |  20 | 人事部    |
|  5 | lili     |  20 | 技术部    |
|  5 | lili     |  20 | 财务部    |
|  5 | lili     |  20 | 运营部    |
|  6 | oven     |  23 | 人事部    |
|  6 | oven     |  23 | 技术部    |
|  6 | oven     |  23 | 财务部    |
|  6 | oven     |  23 | 运营部    |
+----+----------+-----+-----------+
24 rows in set (0.00 sec)
复制代码

内连接的形式

查询两个表中符合连接条件的记录(取交集)

语法:SELECT 字段名称,... FROM 表名1 INNER JOIN 表名2 ON 连接条件 INNER JOIN 表名3 ON 连接条件...;(INNER 可以省略)

SELECT e.id,e.username,e.age,d.dep_name
FROM emp AS e
INNER JOIN dep AS d
ON e.dep_id = d.id;
+----+----------+-----+-----------+
| id | username | age | dep_name  |
+----+----------+-----+-----------+
|  1 | tom      |  20 | 技术部    |
|  2 | john     |  23 | 人事部    |
|  3 | mike     |  20 | 财务部    |
|  4 | rose     |  23 | 人事部    |
|  5 | lili     |  20 | 运营部    |
|  6 | oven     |  23 | 技术部    |
+----+----------+-----+-----------+
复制代码

外链接的形式

INSERT dep SET dep_name='法务部',dep_desc='法务工作';
INSERT emp SET username='nico',age=19,dep_id=10;
复制代码

左外连接

先显示左表中的全部记录,再去右表中查询符合条件的记录,不符合的以NULL代替

语法:SELECT 字段名,... FROM 表名1 LEFT OUTER JOIN 表名2 ON 条件;(OUTER 可省略)

SELECT e.id,e.username,e.age,d.dep_name,d.dep_desc
FROM emp AS e
LEFT OUTER JOIN dep AS d
ON e.dep_id = d.id;

+----+----------+-----+-----------+--------------+
| id | username | age | dep_name  | dep_desc     |
+----+----------+-----+-----------+--------------+
|  1 | tom      |  20 | 技术部    | 研发         |
|  6 | oven     |  23 | 技术部    | 研发         |
|  2 | john     |  23 | 人事部    | 人事工作     |
|  4 | rose     |  23 | 人事部    | 人事工作     |
|  3 | mike     |  20 | 财务部    | 财务工作     |
|  5 | lili     |  20 | 运营部    | 运营工作     |
|  7 | nico     |  19 | NULL      | NULL         |
+----+----------+-----+-----------+--------------+
复制代码

右外连接

先显示右表中的全部记录,再去左表中查询符合条件的记录,不符合的以NULL代替

语法:SELECT 字段名,... FROM 表名1 RIGHT OUTER JOIN 表名2 ON 条件;(OUTER 可省略)

SELECT e.id,e.username,e.age,d.dep_name,d.dep_desc
FROM emp AS e
RIGHT OUTER JOIN dep AS d
ON e.dep_id = d.id;

+------+----------+------+-----------+--------------+
| id   | username | age  | dep_name  | dep_desc     |
+------+----------+------+-----------+--------------+
|    1 | tom      |   20 | 技术部    | 研发         |
|    2 | john     |   23 | 人事部    | 人事工作     |
|    3 | mike     |   20 | 财务部    | 财务工作     |
|    4 | rose     |   23 | 人事部    | 人事工作     |
|    5 | lili     |   20 | 运营部    | 运营工作     |
|    6 | oven     |   23 | 技术部    | 研发         |
| NULL | NULL     | NULL | 法务部    | 法务工作     |
+------+----------+------+-----------+--------------+
复制代码

外键约束

只有INNODB存储引擎支持外键约束

  • 建表时指定外键

语法: [CONSTRAINT 外键名称]FOREIGH KEY (字段名) REFERENCES 表名(字段名); 外键名称可省略

子表的外键字段和父表字段类型要相似,如果是数值型要求一致,有无符号位也要一致,如果是字符型,要求类型一致,长度可以不同

如果外键字段没有创建索引,mysql会自动添加一个普通索引

子表的外键关联的必须是父表的主键

-- 创建父表
CREATE TABLE `news_cate` (
	`id` TINYINT (3) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '编号',
	`cateName` VARCHAR (50) NOT NULL COMMENT '分类名称',
	`cateDesc` VARCHAR (100) NOT NULL DEFAULT '' COMMENT '分类描述',
	PRIMARY KEY (`id`),
	UNIQUE KEY `cate_name` (`cateName`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;

-- 创建子表
CREATE TABLE `news` (
	`id` INT (10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '编号',
	`title` VARCHAR (100) NOT NULL COMMENT '新闻标题',
	`content` VARCHAR (1000) NOT NULL COMMENT '新闻内容',
	`cateId` TINYINT (3) UNSIGNED NOT NULL COMMENT '新闻所属分类id',
	PRIMARY KEY (`id`),
	UNIQUE KEY `title` (`title`),
	CONSTRAINT cateId__fk__news_cate FOREIGN KEY (`cateId`) REFERENCES `news_cate` (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;

-- 插入数据
INSERT news_cate (cateName)
VALUES
	('国内新闻'),
	('国际新闻'),
	('娱乐新闻'),
	('体育新闻');

INSERT news (title, content, cateId)
VALUES
	('a1', 'aaaa1', 1),
	('a2', 'aaaa2', 1),
	('a3', 'aaaa3', 4),
	('a4', 'aaaa4', 2),
	('a5', 'aaaa5', 3);
	

-- 当插入数据不符合要求时报错
INSERT news (title, content, cateId) VALUES ('a10', 'aaaa10', 10);
ERROR 1452 (23000):Cannot add or update a child row: a foreign key constraint fails (`test`.`news`, CONSTRAINT `cateId__fk__news_cate` FOREIGN KEY (`cateId`) REFERENCES `news_cate` (`id`))
-- 删除父表或父表中的记录时,要确保被删除的内容没有被子表引用,有则先删除子表中的引用再做删除
-- 修改父表中的id时,要确保被修改的id没有被子表引用,有则先删除子表中的引用在做修改
复制代码
  • 动态删除、添加外键

删除外键 :ALTER TABLE 表名 DROP FOREIGN KEY 外键名;

ALTER TABLE news DROP FOREIGN KEY cateId__fk__news_cate;
SHOW CREATE TABLE news;
+-----------------------------------------------------------------------
CREATE TABLE `news` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '编号',
  `title` varchar(100) NOT NULL COMMENT '新闻标题',
  `content` varchar(1000) NOT NULL COMMENT '新闻内容',
  `cateId` tinyint(3) unsigned NOT NULL COMMENT '新闻所属分类id',
  PRIMARY KEY (`id`),
  UNIQUE KEY `title` (`title`),
  KEY `cateId__fk__news_cate` (`cateId`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
+-----------------------------------------------------------------------
复制代码

添加外键 :ALTER TABLE 表名 ADD FOREIGN KEY (外键字段名) REFERENCES 父表(主键字段名);

动态添加外键需要确保表中记录是合法的

ALTER TABLE news ADD CONSTRAINT cateId__fk__news_cate FOREIGN KEY (cateId) REFERENCES news_cate (id);
SHOW CREATE TABLE news;
+-----------------------------------------------------------------------
CREATE TABLE `news` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '编号',
  `title` varchar(100) NOT NULL COMMENT '新闻标题',
  `content` varchar(1000) NOT NULL COMMENT '新闻内容',
  `cateId` tinyint(3) unsigned NOT NULL COMMENT '新闻所属分类id',
  PRIMARY KEY (`id`),
  UNIQUE KEY `title` (`title`),
  KEY `cateId__fk__news_cate` (`cateId`),
  CONSTRAINT `cateId__fk__news_cate` FOREIGN KEY (`cateId`) REFERENCES `news_cate` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
+-----------------------------------------------------------------------
复制代码

外键约束的参照操作

  • CASCADE 级联操作 从父表中删除或者更新,子表也跟着删除或者更新
  • SET NULL 从父表中删除或更新记录,并设置字表的外键列为NULL 需要取消该列NOT NULL 约束
  • NO ACTION | RESTRICT 拒绝父表做更新和删除操作(默认)

语法: [CONSTRAINT 外键名称]FOREIGH KEY (字段名) REFERENCES 表名(字段名) ON DELET CASCADE ON UPDATE CASCADE;

转载于:https://juejin.im/post/5c1757c0e51d4546f83c8ff0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值