知识点七:连接查询(37-41)
什么是连接查询:
连接查询是将两个或两个以上的表按某个条件连接起来,从中选取需要的数据。连接查询是同时查询两个或两个以上的表时使用的。当不同的表中存在相同意义的字段时,可以通过该字段连接这几个表。
1 -- 查询cms_user id,username 2 -- provinces,proName 3 SELECT cms_user.id,username,proName FROM cms_user,provinces; --笛卡儿积 4 5 -- cms_user的proId对应省份表中的id 6 SELECT cms_user.id,username,proName FROM cms_user,provinces 7 WHERE cms_user.proId=provinces.id;
内连接查询:
CROSS JOIN | INNER JOIN | JOIN
通过ON 连接查询
显示两个表中符合连接条件的记录
1 -- 查询cms_user表中id,username,email,sex 2 -- 查询provinces表proName 3 SELECT u.id,u.username,u.email,u.sex,p.proName 4 FROM cms_user AS u 5 INNER JOIN provinces AS p 6 ON u.proId=p.id; 7 8 9 SELECT u.id,u.username,u.email,u.sex,p.proName 10 FROM provinces AS p 11 CROSS JOIN cms_user AS u 12 ON u.proId=p.id; 13 14 15 SELECT u.id,u.username,u.email,u.sex,p.proName 16 FROM provinces AS p 17 JOIN cms_user AS u 18 ON u.proId=p.id; 19 20 21 -- 查询cms_user id,username,sex 22 -- 查询provinces proName 23 -- 条件是cms_user的性别为男的用户 24 SELECT u.id,u.username,u.sex,p.proName 25 FROM cms_user AS u 26 JOIN 27 provinces AS p 28 ON u.proId=p.id 29 WHERE u.sex='男'; 30 31 -- 根据proName分组 32 SELECT u.id,u.username,u.sex,p.proName,COUNT(*) AS totalUsers,GROUP_CONCAT(username) 33 FROM cms_user AS u 34 JOIN 35 provinces AS p 36 ON u.proId=p.id 37 WHERE u.sex='男' 38 GROUP BY p.proName; 39 40 -- 对分组结果进行筛选,选出组中人数>=1的 41 SELECT u.id,u.username,u.sex,p.proName,COUNT(*) AS totalUsers,GROUP_CONCAT(username) 42 FROM cms_user AS u 43 JOIN 44 provinces AS p 45 ON u.proId=p.id 46 WHERE u.sex='男' 47 GROUP BY p.proName 48 HAVING COUNT(*)>=1; 49 50 51 -- 按照id升序排列 52 SELECT u.id,u.username,u.sex,p.proName,COUNT(*) AS totalUsers,GROUP_CONCAT(username) 53 FROM cms_user AS u 54 JOIN 55 provinces AS p 56 ON u.proId=p.id 57 WHERE u.sex='男' 58 GROUP BY p.proName 59 HAVING COUNT(*)>=1 60 ORDER BY u.id ASC; 61 62 63 -- 限制显示条数 前2条 64 SELECT u.id,u.username,u.sex,p.proName,COUNT(*) AS totalUsers,GROUP_CONCAT(username) 65 FROM cms_user AS u 66 JOIN 67 provinces AS p 68 ON u.proId=p.id 69 WHERE u.sex='男' 70 GROUP BY p.proName 71 HAVING COUNT(*)>=1 72 ORDER BY u.id ASC 73 LIMIT 0,2; 74 75 -- 查询cms_news中的id,title, 76 -- 查询cms_cate 中的cateName 77 SELECT n.id,n.title,c.cateName FROM 78 cms_news AS n 79 JOIN 80 cms_cate AS c 81 ON n.cId=c.id; 82 83 -- cms_news id,title 84 -- cms_admin username,role 85 SELECT n.id,n.title,a.username,a.role 86 FROM 87 cms_news AS n 88 JOIN 89 cms_admin AS a 90 ON n.aId=a.id; 91 92 -- cms_news id ,title 93 -- cms_cate cateName 94 -- cms_admin username,role 95 SELECT n.id,n.title,c.cateName,a.username,a.role 96 FROM cms_cate AS c 97 JOIN 98 cms_news AS n 99 ON n.cId=c.id 100 JOIN 101 cms_admin AS a 102 ON n.aId=a.id;
外连接查询:
左外连接:LEFT [OUTER] JOIN
显示左表的全部记录及右表符合连接条件的记录
右外连接:RIGHT [OUTER] JOIN
显示右表的全部记录以及左表符合连接条件的记录
1 -- 插入错误的数据 2 INSERT cms_user(username,password,regTime,proId) 3 VALUES('TEST2','TEST2','1381203974',20); 4 5 6 -- 左外连接 7 SELECT u.id,u.username,u.email,u.sex,p.proName 8 FROM cms_user AS u 9 LEFT JOIN provinces AS p 10 ON u.proId=p.id; 11 12 13 SELECT u.id,u.username,u.email,u.sex,p.proName 14 FROM provinces AS p 15 LEFT JOIN cms_user AS u 16 ON u.proId=p.id; 17 18 19 -- 右外连接 20 SELECT u.id,u.username,u.email,u.sex,p.proName 21 FROM provinces AS p 22 RIGHT JOIN cms_user AS u 23 ON u.proId=p.id; 24 25 SELECT u.id,u.username,u.email,u.sex,p.proName 26 FROM provinces AS p 27 RIGHT JOIN cms_user AS u 28 ON u.proId=p.id;
外键:
外键是表的一个特殊字段,被参照的是主表,外键所在字段的表为子表。设置外键的原则需要记住,就是依赖于数据库中已存在的表的主键。外键的作用是建立该表与其父表的关联关系。父表中对记录做操作时,子表中与之对应的信息也应右相应的改变。
外键的作用时保持数据的一致性和完整性,可以实现一对一或一对多的关系。
注意:
父表和子表必须使用相同的存储引擎,而且禁止使用临时表。
数据表的存储引擎只能是InnoDB
外键列和参照列必须具有相似的数据类型。其中数字的长度或是否有符号位必须相同;而字符的长度则可以不同。
外键列和参照列必须创建索引。如果外键列不存在索引的话 ,MySQL将自动创建索引。
外键约束的参照操作:
CASCADE:从父表删除或者更新且自动删除或更新子表中匹配的行。
1 --删除部门表和员工表重新创建 2 ---------------- 3 CREATE TABLE IF NOT EXISTS department( 4 id TINYINT UNSIGNED AUTO_INCREMENT KEY, 5 depName VARCHAR(20) NOT NULL UNIQUE 6 )ENGINE=INNODB; 7 8 INSERT department(depName) VALUES('教学部'), 9 ('市场部'), 10 ('运营部'), 11 ('督导部'); 12 13 --(当父表进行删除或更新时子表自动删除或者更新) CASCADE 14 -- 创建员工表employee(子表) 15 -- id ,username ,depId 16 CREATE TABLE IF NOT EXISTS employee( 17 id SMALLINT UNSIGNED AUTO_INCREMENT KEY, 18 username VARCHAR(20) NOT NULL UNIQUE, 19 depId TINYINT UNSIGNED, 20 FOREIGN KEY(depId) REFERENCES department(id) ON DELETE CASCADE ON UPDATE CASCADE 21 )ENGINE=INNODB; 22 23 INSERT employee(username,depId) VALUES('king',1), 24 ('queen',2), 25 ('张三',3), 26 ('李四',4), 27 ('王五',1); 28 29 -- 删除部门表中的第一个部门 30 DELETE FROM department WHERE id=1; 31 32 UPDATE department SET id=id+10;
SET NULL:从父表删除或更新行,并设置子表中的外键列为NULL。如果使用该选项,必须保证子表列没有指定的NOT NULL。
1 --SET NULL 2 DROP TABLE employee,department; 3 -------------------- 4 CREATE TABLE IF NOT EXISTS department( 5 id TINYINT UNSIGNED AUTO_INCREMENT KEY, 6 depName VARCHAR(20) NOT NULL UNIQUE 7 )ENGINE=INNODB; 8 9 INSERT department(depName) VALUES('教学部'), 10 ('市场部'), 11 ('运营部'), 12 ('督导部'); 13 14 -- 创建员工表employee(子表) 15 -- id ,username ,depId 16 CREATE TABLE IF NOT EXISTS employee( 17 id SMALLINT UNSIGNED AUTO_INCREMENT KEY, 18 username VARCHAR(20) NOT NULL UNIQUE, 19 depId TINYINT UNSIGNED, 20 FOREIGN KEY(depId) REFERENCES department(id) ON DELETE SET NULL ON UPDATE SET NULL 21 )ENGINE=INNODB; 22 23 INSERT employee(username,depId) VALUES('king',1), 24 ('queen',2), 25 ('张三',3), 26 ('李四',4), 27 ('王五',1); 28 --删除部门一,查询员工表内容 29 DELETE FROM department WHERE id=1; 30 UPDATE department SET id=id+10;
RESTRICT:拒绝对父表的删除或更新操作。
NO ACTION:标准MSQL的关键字,在MySQL中与RESTRICT相同。
1 -- 创建部门表department(主表) 2 -- id depName 3 CREATE TABLE IF NOT EXISTS department( 4 id TINYINT UNSIGNED AUTO_INCREMENT KEY, 5 depName VARCHAR(20) NOT NULL UNIQUE 6 )ENGINE=INNODB; 7 INSERT department(depName) VALUES('教学部'), 8 ('市场部'), 9 ('运营部'), 10 ('督导部'); 11 12 -- 创建员工表employee(子表) 13 -- id ,username ,depId 14 CREATE TABLE IF NOT EXISTS employee( 15 id SMALLINT UNSIGNED AUTO_INCREMENT KEY, 16 username VARCHAR(20) NOT NULL UNIQUE, 17 depId TINYINT UNSIGNED 18 )ENGINE=INNODB; 19 INSERT employee(username,depId) VALUES('king',1), 20 ('queen',2), 21 ('张三',3), 22 ('李四',4), 23 ('王五',1); 24 25 --查询员工表的id,username和所在部门名 26 SELECT e.id,e.username,d.depName FROM 27 employee AS e 28 JOIN 29 department AS d 30 ON e.depId=d.id; 31 32 33 -- 删除督导部 34 DELETE FROM department WHERE depName='督导部'; 35 36 --删除部门表和员工表 37 DROP TABLE IF EXISTS department; 38 DROP TABLE IF EXISTS employee; 39 40 --没有外键时,各个表中的数据没有关联,当两个表有关联时,删除其中一个表中的数据时,对另一个表没产生影响。
1 -- 创建部门表department(主表) 2 -- id depName 3 CREATE TABLE IF NOT EXISTS department( 4 id TINYINT UNSIGNED AUTO_INCREMENT KEY, 5 depName VARCHAR(20) NOT NULL UNIQUE 6 )ENGINE=INNODB; 7 INSERT department(depName) VALUES('教学部'), 8 ('市场部'), 9 ('运营部'), 10 ('督导部'); 11 12 -- 创建员工表employee(子表)(有外键) 13 -- id ,username ,depId 14 CREATE TABLE IF NOT EXISTS employee( 15 id SMALLINT UNSIGNED AUTO_INCREMENT KEY, 16 username VARCHAR(20) NOT NULL UNIQUE, 17 depId TINYINT UNSIGNED, 18 FOREIGN KEY(depId) REFERENCES department(id) 19 )ENGINE=INNODB; 20 INSERT employee(username,depId) VALUES('king',1), 21 ('queen',2), 22 ('张三',3), 23 ('李四',4), 24 ('王五',1); 25 26 -- 删除主表中的记录(会报错,得先删除employee表中的depTd为1数据的删除) 27 DELETE FROM department WHERE id=1; 28 29 -- 删除employee中的属于1部门的人,再删除主表中id为1的数据 30 DELETE FROM employee WHERE depId=1; 31 DELETE FROM department WHERE id=1; 32 33 --在子表中添加数据时,当与主表中关联的数据在主表中查不到时也会报错 34 INSERT employee(username,depId) VALUES('test',11);
1 -- 删除员工表 2 DROP TABLE employee; 3 4 --自定义外键名称 5 CREATE TABLE IF NOT EXISTS employee( 6 id SMALLINT UNSIGNED AUTO_INCREMENT KEY, 7 username VARCHAR(20) NOT NULL UNIQUE, 8 depId TINYINT UNSIGNED, 9 CONSTRAINT emp_fk_dep FOREIGN KEY(depId) REFERENCES department(id) 10 )ENGINE=INNODB; 11 12 13 INSERT employee(username,depId) VALUES('king',3), 14 ('queen',2), 15 ('张三',3), 16 ('李四',4), 17 ('王五',2); 18 19 -- 删除外键(没删除索引) 20 ALTER TABLE employee DROP FOREIGN KEY emp_fk_dep; 21 22 --删除部门表id为2的部门 23 DELETE FROM department WHERE id=2; 24 25 -- 添加外键(不成功以为刚才删除了部门表id为2的部门但员工表还有索引指向2部门) 26 ALTER TABLE employee ADD CONSTRAINT emp_fk_dep FOREIGN KEY(depId) REFERENCES department(id); 27 28 --删除员工表depId为2的员工才能添加上 29 DELETE FROM employee WHERE depId=2; 30 --再添加就成功了 31 ALTER TABLE employee ADD CONSTRAINT emp_fk_dep FOREIGN KEY(depId) REFERENCES department(id);
联合查询:
UNION:
UNION ALL:
UNION和UNION ALL区别是UNION去掉相同记录,UNION ALL是简单的合并到一起。
1 -- 联合查询(两个表查询数量必须一样) 2 SELECT username FROM employee UNION SELECT username FROM cms_user; 3 4 SELECT username FROM employee UNION ALL SELECT username FROM cms_user; 5 6 SELECT id,username FROM employee UNION ALL SELECT username,age FROM cms_user;