一, 插入数据insert into
# 插入完整数据(顺序插入)
语法一:
insert into 表名(字段1,字段2,字段3…字段n) values(值1,值2,值3…值n);
语法二:
insert into 表名 values (值1,值2,值3…值n);
# 指定字段插入数据
语法:
insert into 表名(字段1,字段2,字段3…) values (值1,值2,值3…);
# 插入多条记录
语法:
insert into 表名 values
(值1,值2,值3…值n),
(值1,值2,值3…值n),
(值1,值2,值3…值n);
# 插入查询结果
语法:
insert into 表名(字段1,字段2,字段3…字段n)
select (字段1,字段2,字段3…字段n) from 表2
where …;
二, 更新数据update
语法:
update 表名 set
字段1=值1,
字段2=值2,
where 条件;
示例:
UPDATE mysql.user SET password=password(‘123’)
where user=’root’ and host=’localhost’;
三, 删除数据delete
语法:
delete from 表名
where 条件;
示例:
delete from mysql.user
where password=’’;
四, 查询数据 search
一,单表查询
-
单表查询语法
SELECT DISTINCT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY field LIMIT 限制条数
-
关键字执行的优先级
关键字 作用 from 找到表 where 拿着where指定的约束条件,去文件/表中取出一条条记录 group by 将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组 having 将分组的结果进行having过滤 select distinct 执行select(去重) order by 将结果按条件排序:order by limit 限制结果的显示条数 -
简单查询
# 示例表的信息 mysql> create table employee( -> id int primary key auto_increment, -> emp_name varchar(20) not null, -> sex enum('男','女') not null default '男', # 大部分是男的 -> age int(3) unsigned not null default 18, -> hire_date date not null, -> post varchar(50), -> post_comment varchar(100), -> salary double(15,2), -> office int, # 一个部门一个屋子 -> depart_id int -> ); mysql> desc employee; +--------------+-------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+-------------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | emp_name | varchar(20) | NO | | NULL | | | sex | enum('男','女') | NO | | 男 | | | age | int(3) unsigned | NO | | 18 | | | hire_date | date | NO | | NULL | | | post | varchar(50) | YES | | NULL | | | post_comment | varchar(100) | YES | | NULL | | | salary | double(15,2) | YES | | NULL | | | office | int(11) | YES | | NULL | | | depart_id | int(11) | YES | | NULL | | +--------------+-------------------+------+-----+---------+----------------+ mysql> insert into employee(emp_name,sex,age,hire_date,post,salary,office,depart_id) values -> ('孙悟空','男',18,'20170301','develop',7300,401,1), # 以下是开发部门 -> ('猪八戒','男',78,'20150302','develop',1000000,401,1), -> ('唐僧','男',81,'20130305','develop',8300,401,1), -> ('小白龙','男',73,'20140701','develop',3500,401,1), -> ('沙悟净','男',28,'20121101','develop',2100,401,1), -> ('太上老君','女',18,'20110211','develop',9000,401,1), -> ('元始天尊','男',18,'19000301','develop',30000,401,1), -> ('通天教主','男',48,'20101111','develop',10000,401,1), -> -> ('歪歪','女',48,'20150311','sale',3000,402,2),# 以下是销售部门 -> ('丫丫','女',38,'20101101','sale',2000,402,2), -> ('丁丁','女',18,'20110312','sale',1000,402,2), -> ('星星','女',18,'20160513','sale',3000,402,2), -> ('格格','女',28,'20170127','sale',4000,402,2), -> -> ('李世民','男',28,'20160311','operation',10000,403,3), # 以下是运营部门 -> ('程咬金','男',18,'19970312','operation',20000,403,3), -> ('程咬银','女',18,'20130311','operation',19000,403,3), -> ('程咬铜','男',18,'20150411','operation',18000,403,3), -> ('程咬铁','女',18,'20140512','operation',17000,403,3) -> ;
# 简单查询 mysql> select * from employee; mysql> select emp_name,salary from employee; # 避免重复DISTINCT mysql> select distinct post from employee; # 通过四则运算查询 mysql> select emp_name,salary*12 from employee; # 定义显示格式 concat() 函数用于连接字符串 mysql> select concat('姓名:',emp_name,' 年薪:',salary*12) as Annual_salary # as 新字段名 -> from employee; mysql> select concat('姓名:',emp_name,' 年薪:',salary*12) Annual_salary -> from employee; # 不用as也可以 +---------------------------------------+ | Annual_salary | +---------------------------------------+ | 姓名:孙悟空 年薪:87600.00 | | ... | +---------------------------------------+ # CONCAT_WS() 第一个参数为连接符 mysql> select concat_ws(':',emp_name,salary*12) as Annual_salary -> from employee; +------------------------+ | Annual_salary | +------------------------+ | 孙悟空:87600.00 | | ... | +------------------------+ # 结合case语句 mysql> select -> ( case -> when emp_name='通天教主' then -> emp_name -> when emp_name='孙悟空' then -> concat(emp_name,'齐天大圣') -> else -> concat(emp_name,'打工仔') -> end ) as person -> from employee;
-
where约束
select 字段名 from 表名 where 条件
类型 用法 比较运算符 > < >= <= <> != between 80 and 100 值在80到100之间(包含80,100) in(80,90,100) 值是80或90或100 like 'e%' 通配符可以是%或_,%表示任意多字符, _表示一个字符 regexp 正则匹配 is / is not is null / is not null 逻辑运算符 and or not # 1:单条件查询 mysql> select emp_name from employee -> where post='sale'; # 2:多条件查询 mysql> select emp_name,salary from employee -> where post='develop' and salary>10000; # 3:关键字between on mysql> select emp_name,salary from employee -> where salary between 10000 and 20000; mysql> select emp_name,salary from employee -> where salary not between 10000 and 20000; # 4:关键字IS NULL(判断某个字段是否为NULL不能用等号,需要用IS) mysql> select emp_name,post_comment from employee -> where post_comment is null; mysql> select emp_name,post_comment from employee -> where post_comment is not null; mysql> select emp_name,post_comment from employee -> where post_comment=''; # 注意''是空字符串,不是null # 5:关键字IN集合查询 mysql> select emp_name,salary from employee -> where salary=3000 or salary=3500 or salary=4000 or salary=9000; mysql> select emp_name,salary from employee -> where salary in(3000,3500,4000,9000); mysql> select emp_name,salary from employee -> where salary not in (3000,3500,4000,9000); # 6:关键字like模糊查询 # 通配符’%’ mysql> select * from employee -> where emp_name like('程%'); # 通配符’_’ mysql> select * from employee -> where emp_name like('程咬_');
-
group by分组
根据某个重复率比较高的字段进行的,这个字段有多少种可能就分成多少组,能够做到去重,一旦分组了就不能对具体某一条数据进行操作了,永远都是考虑这个组的操作.对unique字段进行分组毫无意义. 单独使用group by关键字分组 select post from employee group by post; 注意: 我们按照post字段分组,那么select查询的字段只能是post,想要获取组内的其他相关信息,需要借助函数 group_concat(): 只用于做最终的显示,不能作为中间结果操作其他数据 group by与聚合函数一起使用: select post,conut(id) as count from employee group by post; 按照岗位分组,并查看每个组有多少人
-
聚合函数
绝大多数情况是和分组一起使用的,如果没有和分组一起使用,那么一整张表就是一组
聚合函数 作用 count() 计数:每个组对应几条数据 max() 求最大值:这个组中某字段的最大值 min() 求最大值:这个组中某字段的最小值 avg() 求平均值 sum() 求和 # 示例 # 查询男员工个数与男员工的平均薪资,女员工个数与女员工的平均薪资 select sex,count(id),avg(salary) from employee group by sex; # 查询岗位名以及各岗位的最高薪资 select post,max(salary) from employee group by post;
-
having过滤
-
主要用于对组进行筛选
-
和where不同在于:
# 执行优先级从高到低:where > group by > having # 1. Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数 # 2. Having发生在分组group by之后,因而Having中可以使用分组的字段,无法直接取到其他字段,可以使用聚合函数
-
-
order by查询排序
按单列排序: select * from employee order by salary; 默认升序 select * from employee order by salary asc; 升序 select * from employee order by salary desc; 降序 按多列排序: 先按照age排序,如果年纪相同,则按照薪资排序 select * from employee order by age asc,salary desc;
-
limit限制查询的记录数
1.显示分页 2.取前n名,总是跟order by一起用 示例: # 默认初始位置为0 select * from employee order by salary desc limit 3; # 从第m开始,即先查询出第m+1条,然后包含这一条在内往后查n条 select * from employee order by salary desc limit m,n; select * from employee order by salary desc limit n offset m; # 同上,从m+1开始取条
二, 多表查询
一, 连表查询
-
示例用表
# 建表 mysql> create table post( -> id int, -> name varchar(20) -> ); mysql> create table employee( -> id int primary key auto_increment, -> name varchar(20), -> sex enum('男','女') not null default '男', -> age int, -> post_id int -> ); # 插入数据 mysql> insert into post values -> (200,'技术'), -> (201,'人力资源'), -> (202,'销售'), -> (203,'运营'); mysql> insert into employee(name,sex,age,post_id) values -> ('孙悟空','男',18,200), -> ('猪八戒','女',48,201), -> ('沙悟净','男',38,201), -> ('唐僧','女',28,202), -> ('小白龙','男',18,200), -> ('哪吒','女',18,204) -> ; # 查看数据 mysql> select * from post; +------+--------------+ | id | name | +------+--------------+ | 200 | 技术 | | 201 | 人力资源 | | 202 | 销售 | | 203 | 运营 | +------+--------------+ mysql> select * from employee; +----+-----------+-----+------+---------+ | id | name | sex | age | post_id | +----+-----------+-----+------+---------+ | 1 | 孙悟空 | 男 | 18 | 200 | | 2 | 猪八戒 | 女 | 48 | 201 | | 3 | 沙悟净 | 男 | 38 | 201 | | 4 | 唐僧 | 女 | 28 | 202 | | 5 | 小白龙 | 男 | 18 | 200 | | 6 | 哪吒 | 女 | 18 | 204 | +----+-----------+-----+------+---------+
-
语法
select 字段 from 表1 inner/left/right join 表2 on 表1.字段 = 表2.字段;
-
交叉连接: 不适用任何匹配条件,生成笛卡尔积,再根据条件进行筛选,但是不能对查询到表再进行操作
mysql> select * from employee,post where post_id=post.id; +----+-----------+-----+------+---------+------+--------------+ | id | name | sex | age | post_id | id | name | +----+-----------+-----+------+---------+------+--------------+ | 1 | 孙悟空 | 男 | 18 | 200 | 200 | 技术 | | 2 | 猪八戒 | 女 | 48 | 201 | 201 | 人力资源 | | 3 | 沙悟净 | 男 | 38 | 201 | 201 | 人力资源 | | 4 | 唐僧 | 女 | 28 | 202 | 202 | 销售 | | 5 | 小白龙 | 男 | 18 | 200 | 200 | 技术 | +----+-----------+-----+------+---------+------+--------------+
-
内连接: 只会显示两张表中互相匹配的项,其他不匹配的不显示
# select * from 表1 inner join 表2 on 条件; # 找两张表共有的部分,相当于利用条件从笛卡尔积结果中筛选出了正确的结果 # post没有204这个部门,因而employee表中关于204这条员工信息没有匹配出来 mysql> select e.id,e.name,age,sex,p.name from employee as e inner join post as p on post_id=p.id; +----+-----------+------+-----+--------------+ | id | name | age | sex | name | +----+-----------+------+-----+--------------+ | 1 | 孙悟空 | 18 | 男 | 技术 | | 2 | 猪八戒 | 48 | 女 | 人力资源 | | 3 | 沙悟净 | 38 | 男 | 人力资源 | | 4 | 唐僧 | 28 | 女 | 销售 | | 5 | 小白龙 | 18 | 男 | 技术 | +----+-----------+------+-----+--------------+
-
外连接之左连接: 不管左表中是不是匹配上都会显示所有内容
# select * from 表1 left join 表2 on 条件; # 以左表为准,即找出所有员工信息,当然包括没有部门的员工 # 本质就是: 在内连接的基础上增加左边有右边没有的结果 mysql> select e.id,e.name,post.name as post_name from employee as e left join post on post_id=post.id; +----+-----------+--------------+ | id | name | post_name | +----+-----------+--------------+ | 1 | 孙悟空 | 技术 | | 5 | 小白龙 | 技术 | | 2 | 猪八戒 | 人力资源 | | 3 | 沙悟净 | 人力资源 | | 4 | 唐僧 | 销售 | | 6 | 哪吒 | NULL | +----+-----------+--------------+
-
外链接之右连接: 不管右表中是不是匹配上都会显示所有内容
# select * from 表1 right join 表2 on 条件 # 以右表为准,即找出所有部门信息,包括没有员工的部门 # 本质就是: 在内连接的基础上增加右边有左边没有的结果 mysql> select e.id,e.name,post.name as post_name from employee as e right join post on post_id=post.id; +------+-----------+--------------+ | id | name | post_name | +------+-----------+--------------+ | 1 | 孙悟空 | 技术 | | 2 | 猪八戒 | 人力资源 | | 3 | 沙悟净 | 人力资源 | | 4 | 唐僧 | 销售 | | 5 | 小白龙 | 技术 | | NULL | NULL | 运营 | +------+-----------+--------------+
-
全外连接: 显示左右两个表全部记录
# 全外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果 # 注意:mysql不支持全外连接 full join # 强调:mysql可以使用此种方式间接实现全外连接 # select * from 表1 left join 表2 on 条件 # union # select * from 表1 right join 表2 on 条件; mysql> select e.id,e.name,post.name as post_name from employee as e left join post on post_id=post.id -> union -> select e.id,e.name,post.name as post_name from employee as e right join post on post_id=post.id; +------+-----------+--------------+ | id | name | post_name | +------+-----------+--------------+ | 1 | 孙悟空 | 技术 | | 5 | 小白龙 | 技术 | | 2 | 猪八戒 | 人力资源 | | 3 | 沙悟净 | 人力资源 | | 4 | 唐僧 | 销售 | | 6 | 哪吒 | NULL | | NULL | NULL | 运营 | +------+-----------+--------------+ # 注意 union与union all的区别: union会去掉相同的纪录
-
符合条件连接查询
# 示例1:以内连接的方式查询employee和psot表,并且employee表中的age字段值必须大于25,即找出年龄大于25岁的员工以及员工所在的部门 mysql> select e.name,post.name as post_name from employee as e inner join post on post_id=post.id where age>25; +-----------+--------------+ | name | post_name | +-----------+--------------+ | 猪八戒 | 人力资源 | | 沙悟净 | 人力资源 | | 唐僧 | 销售 | +-----------+--------------+ # 示例2:以内连接的方式查询employee和post表,并且以age字段的升序方式显示 mysql> select e.name,age,post.name as post_name,post_id from employee as e inner join post on post_id=post.id order by age; +-----------+------+--------------+---------+ | name | age | post_name | post_id | +-----------+------+--------------+---------+ | 孙悟空 | 18 | 技术 | 200 | | 小白龙 | 18 | 技术 | 200 | | 唐僧 | 28 | 销售 | 202 | | 沙悟净 | 38 | 人力资源 | 201 | | 猪八戒 | 48 | 人力资源 | 201 | +-----------+------+--------------+---------+
二, 子查询
# 1:子查询是将一个查询语句嵌套在另一个查询语句中.
# 2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
# 3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
# 4:还可以包含比较运算符:= 、 !=、> 、<等
-
带in关键字的子查询
# 查询平均年龄在25岁以上的部门名 mysql> select name from post where id in (select post_id from employee group by post_id having avg(age)>25); +--------------+ | name | +--------------+ | 人力资源 | | 销售 | +--------------+ # 查看技术部员工姓名 mysql> select name from employee where post_id=(select id from post where name='技术'); +-----------+ | name | +-----------+ | 孙悟空 | | 小白龙 | +-----------+ # 查看不足1人的部门名(子查询得到的是有人的部门id) mysql> select name from post where id not in (select post_id from employee); +--------+ | name | +--------+ | 运营 | +--------+
-
带比较运算符的子查询
# 查询大于所有人平均年龄的员工名与年龄 mysql> select name,age from employee where age>(select avg(age) from employee); +-----------+------+ | name | age | +-----------+------+ | 猪八戒 | 48 | | 沙悟净 | 38 | +-----------+------+ # 查询大于部门内平均年龄的员工名、年龄 mysql> select name,post_id from employee inner join (select post_id as post_id2,avg(age) as avg_age from employee group by post_id) as emp on post_id=post_id2 where age>avg_age; +-----------+---------+ | name | post_id | +-----------+---------+ | 猪八戒 | 201 | +-----------+---------+
-
带exists关键字的子查询
exists关键字表示存在,在使用exists关键字时,内层查询语句不返回查询的记录.而是返回一个真假值,True或False.当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询
# post表中存在id=200,Ture mysql> select * from employee -> where exists -> (select id from psot where id=200); # post表中不存在id=205,False mysql> select * from employee -> where exists -> (select id from post where id=205);
-
练习: 查询每个部门最新入职的那位员工
# 准备表和数据 mysql> create table emp( -> id int primary key auto_increment, -> emp_name varchar(20) not null, -> sex enum('男','女') not null default '男', # 大部分是男的 -> age int(3) unsigned not null default 18, -> hire_date date not null, -> post varchar(50), -> post_comment varchar(100), -> salary double(15,2), -> office int, # 一个部门一个屋子 -> depart_id int -> ); mysql> insert into emp(emp_name,sex,age,hire_date,post,salary,office,depart_id) values -> ('孙悟空','男',18,'20170301','develop',7300,401,1), # 以下是开发部门 -> ('猪八戒','男',78,'20150302','develop',1000000,401,1), -> ('唐僧','男',81,'20130305','develop',8300,401,1), -> ('小白龙','男',73,'20140701','develop',3500,401,1), -> ('沙悟净','男',28,'20121101','develop',2100,401,1), -> ('太上老君','女',18,'20110211','develop',9000,401,1), -> ('元始天尊','男',18,'19000301','develop',30000,401,1), -> ('通天教主','男',48,'20101111','develop',10000,401,1), -> ('歪歪','女',48,'20150311','sale',3000,402,2),# 以下是销售部门 -> ('丫丫','女',38,'20101101','sale',2000,402,2), -> ('丁丁','女',18,'20110312','sale',1000,402,2), -> ('星星','女',18,'20160513','sale',3000,402,2), -> ('格格','女',28,'20170127','sale',4000,402,2), -> ('李世民','男',28,'20160311','operation',10000,403,3), # 以下是运营部门 -> ('程咬金','男',18,'19970312','operation',20000,403,3), -> ('程咬银','女',18,'20130311','operation',19000,403,3), -> ('程咬铜','男',18,'20150411','operation',18000,403,3), -> ('程咬铁','女',18,'20140512','operation',17000,403,3);
# 连表查询 mysql> select emp.post,emp_name,max_date from emp inner join (select post,max(hire_date) as max_date from emp group by post) as emp2 -> on emp.post=emp2.post where hire_date=max_date; +-----------+-----------+------------+ | post | emp_name | max_date | +-----------+-----------+------------+ | develop | 孙悟空 | 2017-03-01 | | sale | 格格 | 2017-01-27 | | operation | 李世民 | 2016-03-11 | +-----------+-----------+------------+
# 子查询 有缺陷 mysql> select emp_name,hire_date,post from (select * from emp order by hire_date desc) as emp2 group by post; +-----------+------------+-----------+ | emp_name | hire_date | post | +-----------+------------+-----------+ | 孙悟空 | 2017-03-01 | develop | | 李世民 | 2016-03-11 | operation | | 格格 | 2017-01-27 | sale | +-----------+------------+-----------+ mysql> select emp_name,hire_date,post from emp where id in( -> select (select id from emp as t2 where t2.post=t1.post order by hire_date desc limit 1) from emp as t1 group by post -> ); +-----------+------------+-----------+ | emp_name | hire_date | post | +-----------+------------+-----------+ | 孙悟空 | 2017-03-01 | develop | | 格格 | 2017-01-27 | sale | | 李世民 | 2016-03-11 | operation | +-----------+------------+-----------+ # 每个部门可能有>1个为同一时间入职的新员工 # 说明,子查询可以在select后(要求查询的结果必须是一个单行单列的值)和from后使用