一、mysql多表查询
1、多表查询
案例:首先创建表 并插入数据
create table dept( id int primary key auto_increment, name varchar(20) ); insert into dept values(null, '财务部'); insert into dept values(null, '人事部'); insert into dept values(null, '科技部'); insert into dept values(null, '销售部'); create table emp( id int primary key auto_increment, name varchar(20), dept_id int ); insert into emp values(null, '林黛玉', 1); insert into emp values(null, '妙玉', 2); insert into emp values(null, '史湘云', 3); insert into emp values(null, '贾探春', 5);
需求:查询出部门信息和部门所对应的员工信息。
select * from dept, emp;
2、笛卡尔积查询:
- 笛卡尔积查询概念:两张表相乘得出来的结果。如果左边表有m条记录,右边有n条记录,则查询出来的结果就是m*n条。这些查询结果中包含大量错误的结果,通常不会使用这种查询。
select * from dept, emp; select * from dept, emp where emp.dept_id=dept.id; select * from dept d, emp e where e.dept_id=d.id;
3、内连接查询:
- 内连接查询概念:左边表有且右边表也有的记录。
select * from dept d inner join emp e on e.dept_id=d.id;
4、左、右外连接查询及全连接查询
• 左外连接查询:在内连接查询的基础上,加上左边表有而右边表没有的记录 **查询出部门所对应的员工信息, 同时列出那些没有员工的部门 select * from dept d left join emp e on e.dept_id=d.id; • 右外连接查询:在内连接查询的基础上,加上右边表有而左边表没有的记录。 **查询出部门所对应的员工信息, 同时列出那些没有部门的员工 select * from dept d right join emp e on e.dept_id=d.id; • 全外连接查询:在内连接查询的基础上,加上左边表有而右边表没有的记录 和 右边表有而左边表没有的记录。 **查询出部门所对应的员工信息,同时列出那些没有员工的部门及些没有部门的员工 select * from dept d full join emp e on e.dept_id=d.id; ##mysql不支持全外连接查询 **通过union关键字来模拟全外连接查询 select * from dept left join emp on emp.dept_id = dept.id union select * from dept right join emp on emp.dept_id = dept.id;
二、关键字执行顺序
1、查询中用到的关键词主要包含六个,并且他们的顺序依次为 :
select--from--where--group by--having--order by 其中select和from是必须的,其他关键词是可选的。
这六个关键词的执行顺序,与sql语句的书写顺序并不是一样的,而是按照下面的顺序来执行
from--where--group by--having--select--order by。
注意:虽然select在having后执行,但是mysql中仍然可以在having中使用select语句定义的别名。
原因分析:mysql在查询的时候会产生一个临时表,所有的字段名称(别名)在临时表中已经产生,产生了临时表之后才会进行having操作。也就是说mysql内部有一定的解析顺序,解析顺序select优先于having。在这里我个人认为是mysql可能没有将这一点做规范。Oracle中having无法使用select语句内的别名。
2、insert into 和replace into和merge into
- insert into是mysql的基本插入语句。
- replace into 是mysql中的代替插入语句,可以理解为insert into的升级版。replace into在执行的时候,首先会根据指定的主键或者唯一索引判断当前表中是否存在指定的主键或索引,如果主键或唯一索引已经存在,则先将对应的索引的数据删除,然后在索引位置插入replace into中包含的数据。如果主键和唯一索引没有存在,则直接在索引位置插入replace into中包含的数据。
- merge into 是oracle数据库中的代替插入语句。实现方式和replace into类似。
- 执行效率:
- 如果指定索引位置没有数据,insert into和replace into执行效率相差无几,二者效率相同。
- 如果指定位置索引已经存在,insert into语句不能正常执行,replace into语句可以正常执行。
- 注意:虽然replace into比较好使用,但是也存在一定风险:
- replace每次要重新分配自增id;
- replace中执行delete时, 在有外键的情况下会很麻烦;
- 如果delete时定义的有触发器, 则会被执行;
- 副作用也会被传播到replica slave.
- 推荐使用INSERT INTO … ON DUPLICATE KEY UPDATE
ON DUPLICATE KEY UPDATE是mysql特有的一个sql关键字,只能在mysql中使用。 在MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句,而要插入的行与表中现有记录的惟一索引或主键中产生重复值,那么就会发生旧行的更新;如果插入的行数据与现有表中记录的唯一索引或者主键不重复,则执行新纪录插入操作。 比如有这样一张表: create table func(id int primary key,count int,birthday date); insert into func values(1,1,'1990-09-09');--插入一条数据 insert into func values(1,1,'1990-09-09') on duplicate key update count = count+1;--表中有数据,删除原表数据,将新数据插入。 提示两行受到影响,说明先执行的删除操作,然后插入新的数据。 观察到没有任何新数据插入,count字段被更新。(count字段更新是因为刚刚的插入语句中书写了update count = count+1;) 如果不希望任何字段更新,可以写成如下格式: insert into func values(1,1,'1990-09-09') on duplicate key update count = values(count);--再次执行,没有新数据插入到数据库中。
三、mysql内置函数
内置函数众多,不需要每一个都掌握,熟练掌握几个在以后使用即可。可以查看mysql官方文档学习内置函数。
四、其它注意事项
1、在已经存在的表中添加外键。(仅作为了解内容)
alter table tb_name add constraint fk_name foreign key (tb_name.id) references tb_stu(id); 例如:alter table emp add constraint forkey foreign key(dept_id) references dept(id); 该语句是在 tb_name表上添加一个外键约束,引用 tb_stu的主键,fk_name是约束的名字。 删除约束:alter table tb_name drop constraint fk_name ;
2、外键的使用情景:
在不要求吞吐速度而对数据的正确性和安全性要求较高时,推荐使用外键。
如果面对高吞吐量,要求优先保证读取效率时,则不推荐使用外键。
3、删除的时候使用别名:
原句:delete from employee where id = 1; 别名:delete e from employee as e where id =1;