MySQL常用操作--多表联查

时间:2021-11-15 02:20:02

  连接是把不同的表的记录连接到一起的最普遍的方法, 一种错误的观念认为由于MySQL的简单性和源代码的开放性使得他不擅长连接. 其实MySQL从一开始就很好的支持连接(SQL92标准), 这种连接语句可以以多种方法来组合表记录.

1. 内连接查询: 

  最普遍的连接类型, 而且是最均匀的(要求他们构成连接的每一部分的每个表的匹配, 不匹配的行将被排除), 内连接最普遍的例子是相等连接, 也就是连接后的表中的某个字段与每个表中的都相同, 这种情况下, 最后的结果集只包含参加连接的表中与指定字段相符的行.

 

mysql> SELECT * FROM goods;
 ---- ------------- --------- -------- --------- 
| id | productName | price   | cateId | adminId |
 ---- ------------- --------- -------- --------- 
|  1 | iphone9     | 9888.00 |      3 |       1 |
|  2 | adidas      |  388.00 |      2 |       2 |
|  3 | nike        |  888.00 |      2 |       2 |
|  4 | 奶瓶        |  288.00 |      1 |       1 |
 ---- ------------- --------- -------- --------- 
4 rows in set (0.00 sec)

mysql> SELECT * FROM goods_sep;
 ---- ---------- ------------------------ 
| id | cateName | cateDesc               |
 ---- ---------- ------------------------ 
|  1 | 母婴     | 这是对于商品的详细描述 |
|  2 | 服装     | 这是对于商品的详细描述 |
|  3 | 电子     | 这是对于商品的详细描述 |
 ---- ---------- ------------------------ 
3 rows in set (0.00 sec)

mysql> SELECT g.id, g.productName, g.price, gs.cateName
    -> FROM goods AS g
    -> JOIN goods_sep AS gs
    -> ON g.cateId=gs.id;
 ---- ------------- --------- ---------- 
| id | productName | price   | cateName |
 ---- ------------- --------- ---------- 
|  1 | iphone9     | 9888.00 | 电子     |
|  2 | adidas      |  388.00 | 服装     |
|  3 | nike        |  888.00 | 服装     |
|  4 | 奶瓶        |  288.00 | 母婴     |
 ---- ------------- --------- ---------- 
4 rows in set (0.00 sec)


内连接的形式


  查询两个表中符合连接条件的记录:
    SELECT 字段名称,... FROM tbl_name1
    INNER JOIN tbl_name2
    ON 连接条件;

 

--外左连接:

mysql> SELECT g.id, g.productName, g.price, gs.cateName -> FROM goods AS g -> LEFT JOIN goods_sep AS gs -> ON gs.id=g.cateId; ---- ------------- --------- ---------- | id | productName | price | cateName | ---- ------------- --------- ---------- | 1 | iphone9 | 9888.00 | 电子 | | 2 | adidas | 388.00 | 服装 | | 3 | nike | 888.00 | 服装 | | 4 | 奶瓶 | 288.00 | 母婴 | ---- ------------- --------- ---------- 4 rows in set (0.00 sec) mysql> UPDATE goods SET productName=iphone10; ERROR 1062 (23000): Duplicate entry iphone10 for key productName mysql> INSERT INTO goods(productName) VALUES(xiaomi); Query OK, 1 row affected, 2 warnings (0.01 sec) mysql> SELECT * FROM goods; ---- ------------- --------- -------- --------- | id | productName | price | cateId | adminId | ---- ------------- --------- -------- --------- | 1 | iphone9 | 9888.00 | 3 | 1 | | 2 | adidas | 388.00 | 2 | 2 | | 3 | nike | 888.00 | 2 | 2 | | 4 | 奶瓶 | 288.00 | 1 | 1 | | 5 | xiaomi | 100.00 | 0 | 0 | ---- ------------- --------- -------- --------- 5 rows in set (0.00 sec) mysql> SELECT g.id, g.productName, g.price, gs.cateName -> FROM goods AS g -> LEFT JOIN goods_sep AS gs -> ON gs.id=g.cateId; ---- ------------- --------- ---------- | id | productName | price | cateName | ---- ------------- --------- ---------- | 1 | iphone9 | 9888.00 | 电子 | | 2 | adidas | 388.00 | 服装 | | 3 | nike | 888.00 | 服装 | | 4 | 奶瓶 | 288.00 | 母婴 | | 5 | xiaomi | 100.00 | NULL | ---- ------------- --------- ---------- 5 rows in set (0.00 sec)

 

外连接的形式


  左外连接:
    SELECT 字段名称,... FROM tbl_name1
    LEFT [OUTER] JOIN tbl_name2
    ON 条件;
    先显示左表中的全部记录,再去右表中查询复合条件的记录,不符合的以NULL代替


  右外连接:
    SELECT 字段名称,... FROM tbl_name1
    RIGHT [OUTER] JOIN tbl_name2
    ON 条件;
    先显示右表中的全部记录,再去左表中查询复合条件的记录,不符合的以NULL代替

--右外连接:

mysql> SELECT g.id, g.productName, g.price, gs.cateName -> FROM goods AS g -> RIGHT JOIN goods_sep AS gs -> ON gs.id=g.cateId; ------ ------------- --------- ---------- | id | productName | price | cateName | ------ ------------- --------- ---------- | 1 | iphone9 | 9888.00 | 电子 | | 2 | adidas | 388.00 | 服装 | | 3 | nike | 888.00 | 服装 | | 4 | 奶瓶 | 288.00 | 母婴 | ------ ------------- --------- ---------- 4 rows in set (0.01 sec)

 

2. 多表联查:

单表:

mysql>
mysql> SELECT * FROM goods;
 ---- ------------- --------- -------- --------- 
| id | productName | price   | cateId | adminId |
 ---- ------------- --------- -------- --------- 
|  1 | iphone9     | 9888.00 |      3 |       1 |
|  2 | adidas      |  388.00 |      2 |       2 |
|  3 | nike        |  888.00 |      2 |       2 |
|  4 | 奶瓶        |  288.00 |      1 |       1 |
|  5 | xiaomi      |  100.00 |      0 |       0 |
 ---- ------------- --------- -------- --------- 
5 rows in set (0.00 sec)

mysql> SELECT * FROM goods_sep;
 ---- ---------- ------------------------ 
| id | cateName | cateDesc               |
 ---- ---------- ------------------------ 
|  1 | 母婴     | 这是对于商品的详细描述 |
|  2 | 服装     | 这是对于商品的详细描述 |
|  3 | 电子     | 这是对于商品的详细描述 |
 ---- ---------- ------------------------ 
3 rows in set (0.00 sec)

mysql> SELECT * FROM administrate;
ERROR 1146 (42S02): Table test.administrate doesnt exist
mysql> SELECT * FROM administrater;
 ---- ---------- ------------ ------- 
| id | username | email      | proId |
 ---- ---------- ------------ ------- 
|  1 | jack     | [email protected] |     1 |
|  2 | tony     | [email protected] |     2 |
 ---- ---------- ------------ ------- 
2 rows in set (0.00 sec)

多表联查:

mysql> SELECT g.id, g.productName, g.price, gs.cateName, a.username, a.email
    -> FROM goods AS g
    -> JOIN administrater AS a
    -> ON g.adminId=a.id
    -> JOIN goods_sep AS gs
    -> ON g.cateId=gs.id;
 ---- ------------- --------- ---------- ---------- ------------ 
| id | productName | price   | cateName | username | email      |
 ---- ------------- --------- ---------- ---------- ------------ 
|  1 | iphone9     | 9888.00 | 电子     | jack     | Tencent@qq |
|  4 | 奶瓶        |  288.00 | 母婴     | jack     | Tencent@qq |
|  2 | adidas      |  388.00 | 服装     | tony     | Tencent@qq |
|  3 | nike        |  888.00 | 服装     | tony     | Tencent@qq |
 ---- ------------- --------- ---------- ---------- ------------ 
4 rows in set (0.01 sec)

 

3. 外键约束(InnoDB数据库引擎支持)

   外键约束的作用: 保证数据的一致性和完整性.数据的完整性是指数据的正确性和相容性, 是为了防止数据库中存在不符合语义的数据, 即防止数据库中存在不正确的数据, 可以通过CREATE TABLE 或ALTER TABLE 语句来定义. 一旦定义了数据的完整性约束MySQL服务器会随时检测处于更新状态的的数据库内容是否符合相关性的约束, 从而保证数据的一致性与正确性.

 

   例如: 学生实体和班级实体可以分别用下面的关系表示, 其中主键用下划线标识;

   学生(学生证号, 姓名, 性别, 生日, 班级编号, 备注)

   班级(班级编号, 班级名称, 备注)

这两个关系之间存在着属性的引用, 即: "学生"关系引用了"班级"关系中的主键(班级编号).在这两个实体之间, "班级编号"是"班级"关系中的主键, 也是"学生"关系中外键, 显然, "学生"关系中的"班级编号"的取值必须参照"班级"中的属性和值.

  外键的创建:

  •   建表示创建外键:   

    [CONSTRAINT 外键名称 ] FOREIGN KEY(字段名称) REFERENCES 主表(字段名称)
      子表的外键字段和主表的主键字段类型要相似;如果是数值型要求一致,并且无符号也要一致;如果是字符型,要求类型一致,长度可以不同
      如果外键字段没有创建索引,MySQL会自动帮我们添加索引
      子表的外键关联的必须是父表的主键
    外键约束的参照操作:
      CASCADE------从父表删除或更新,子表也跟着删除或者更新,级联的操作
      SET NULL------从父表删除或者更新记录,并设置子表的外键列为NULL。
      NO ACTION | RESTRICT-------拒绝对父表做更新或者删除操作

-- 添加外键

-- 新闻分类表 news_cate
CREATE TABLE news_cate(
id TINYINT UNSIGNED AUTO_INCREMENT KEY,
cateName VARCHAR(50) NOT NULL UNIQUE,
cateDesc VARCHAR(100) NOT NULL DEFAULT 描述
)ENGINE=INNODB CHARSET=UTF8;

-- 新闻表 news
CREATE TABLE news(
id INT UNSIGNED AUTO_INCREMENT KEY,
title VARCHAR(100) NOT NULL UNIQUE,
content VARCHAR(1000) NOT NULL,
cateId TINYINT UNSIGNED NOT NULL,
FOREIGN KEY(cateId) REFERENCES news_cate(id)
)ENGINE=INNODB 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);
mysql> SHOW CREATE TABLE news;
 ------- ------------------------------------------------------------------------------------------ 
| Table | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                   |
 ------- ------------------------------------------------------------------------------------------ 
| news  | CREATE TABLE `news` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `content` varchar(1000) NOT NULL,
  `cateId` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `title` (`title`),
  KEY `cateId_fk_newsCate` (`cateId`),
  CONSTRAINT `cateId_fk_newsCate` FOREIGN KEY (`cateId`) REFERENCES `news_cate` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 |
 ------- ------------------------------------------------------------------------------------------ 
1 row in set (0.00 sec)

mysql> SHOW CREATE TABLE news_cate;
 ----------- -------------------------------------------------------------------------------------- 
| Table     | Create Table                                                                                                                                                                                                                                                                          |
 ----------- -------------------------------------------------------------------------------------- 
| news_cate | CREATE TABLE `news_cate` (
  `id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
  `cateName` varchar(50) NOT NULL,
  `cateDesc` varchar(100) NOT NULL DEFAULT 描述,
  PRIMARY KEY (`id`),
  UNIQUE KEY `cateName` (`cateName`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 |
 ----------- -------------------------------------------------------------------------------------- 
1 row in set (0.00 sec)

 

  • 动态添加外键

  动态添加外键:

    ALTER TABLE tbl_name ADD [CONSTRAINT 外键名称] FOREIGN KEY(外键字段) REFERENCES 主表(主键字段);

    动态添加外键之前表中的记录一定合法的记录,没有脏值,否则外键添加不成功
  动态删除外键:

    ALTER TABLE tbl_name
    DROP FOREIGN KEY fk_name;