mysql记录操作

一, 插入数据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=’’;

一,单表查询

  1. 单表查询语法

    SELECT DISTINCT 字段1,字段2... FROM 表名
                                  WHERE 条件
                                  GROUP BY field
                                  HAVING 筛选
                                  ORDER BY field
                                  LIMIT 限制条数
    
  2. 关键字执行的优先级

    关键字 作用
    from 找到表
    where 拿着where指定的约束条件,去文件/表中取出一条条记录
    group by 将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组
    having 将分组的结果进行having过滤
    select distinct 执行select(去重)
    order by 将结果按条件排序:order by
    limit 限制结果的显示条数
  3. 简单查询

    # 示例表的信息
    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;
    
  4. 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('程咬_');
    
  5. 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; 按照岗位分组,并查看每个组有多少人
    
  6. 聚合函数

    绝大多数情况是和分组一起使用的,如果没有和分组一起使用,那么一整张表就是一组

    聚合函数 作用
    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;
    
  7. having过滤

    • 主要用于对组进行筛选

    • 和where不同在于:

      # 执行优先级从高到低:where > group by > having 
      # 1. Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数
      # 2. Having发生在分组group by之后,因而Having中可以使用分组的字段,无法直接取到其他字段,可以使用聚合函数
      
  8. 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;
    
  9. 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开始取条
    

二, 多表查询

一, 连表查询

  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 |
    +----+-----------+-----+------+---------+
    
  2. 语法

    select 字段 from 表1 inner/left/right join 表2
    		on 表1.字段 = 表2.字段;
    
  3. 交叉连接: 不适用任何匹配条件,生成笛卡尔积,再根据条件进行筛选,但是不能对查询到表再进行操作

    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 | 技术          |
    +----+-----------+-----+------+---------+------+--------------+
    
  4. 内连接: 只会显示两张表中互相匹配的项,其他不匹配的不显示

    # 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 | 男  | 技术          |
    +----+-----------+------+-----+--------------+
    
  5. 外连接之左连接: 不管左表中是不是匹配上都会显示所有内容

    # 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         |
    +----+-----------+--------------+
    
  6. 外链接之右连接: 不管右表中是不是匹配上都会显示所有内容

    # 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      | 运营         |
    +------+-----------+--------------+
    
  7. 全外连接: 显示左右两个表全部记录

    # 全外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果
    # 注意: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会去掉相同的纪录
    
  8. 符合条件连接查询

    # 示例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:还可以包含比较运算符:= 、 !=、> 、<等
  1. 带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   |
    +--------+
    | 运营   |
    +--------+
    
  2. 带比较运算符的子查询

    # 查询大于所有人平均年龄的员工名与年龄
    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 |
    +-----------+---------+
    
  3. 带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);
    
  4. 练习: 查询每个部门最新入职的那位员工

    # 准备表和数据
    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后使用
    
原文地址:https://www.cnblogs.com/zyyhxbs/p/11290306.html