SQL语句的分类

  1. DDL(Data Definition Languages)语句:数据定义语言。这些语句定义了不同的数据段、

    数据库、表、列、索引等数据库对象的定义。常用的语句关键字主要包括create、drop、alter

    等。
  2. DML(Data Manipulation Language)语句:数据操纵语句,用于添加、删除、更新和查

    询数据库记录,并检查数据完整性,常用的语句关键字主要包括insert、delete、udpate 和

    select 等。
  3. DCL(Data Control Language)语句:数据控制语句,用于控制不同数据段直接的许可和

    访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的

    语句关键字包括grant、revoke 等。

DML语句

DML 操作是指对数据库中表记录的操作,主要包括表记录的插入(insert)、更新(update)、

删除(delete)和查询(select),是开发人员日常使用最频繁的操作。下面将依次对它们进

行介绍。

  1. 插入记录

    表创建好后,就可以往里插入记录了,插入记录的基本语法如下:

    1. INSERT INTO tablename (field1,field2,……fieldn) VALUES(value1,value2,……valuesn);

    例如:向表emp 中插入以下记录:ename 为zzx1,hiredate 为2000-01-01,sal 为2000,deptno

    为1,命令执行如下:

    1. mysql> insert into emp (ename,hiredate,sal,deptno) values('zzx1','2000-01-01','2000',1);
    2. Query OK, 1 row affected (0.00 sec)

    也可以不用指定字段名称,但是values 后面的顺序应该和字段的排列顺序一致:

    1. mysql> insert into emp values('lisa','2003-02-01','3000',2);
    2. Query OK, 1 row affected (0.00 sec)

    对于含可空字段、非空但是含有默认值的字段、自增字段,可以不用在insert 后的字段列表

    里面出现,values 后面只写对应字段名称的value,这些没写的字段可以自动设置为NULL、

    默认值、自增的下一个数字,这样在某些情况下可以大大缩短SQL 语句的复杂性。

    例如,只对表中的ename 和sal 字段显式插入值:

    1. mysql> insert into emp (ename,sal) values('dony',1000);
    2. Query OK, 1 row affected (0.00 sec)

    来查看一下实际插入值:

    1. mysql> select * from emp;
    2. +-------+------------+---------+--------+
    3. | ename | hiredate | sal | deptno |
    4. +-------+------------+---------+--------+
    5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    6. | lisa | 2003-02-01 | 3000.00 | 2 |
    7. | dony | NULL | 1000.00 | NULL |
    8. +-------+------------+---------+--------+
    9. 3 rows in set (0.00 sec)

    果然,设置为可空的两个字段都显示为NULL。

    在MySQL 中,insert 语句还有一个很好的特性,可以一次性插入多条记录,语法如下:

    1. INSERT INTO tablename (field1, field2,……fieldn)
    2. VALUES
    3. (record1_value1, record1_value2,……record1_valuesn),
    4. (record2_value1, record2_value2,……record2_valuesn),
    5. ……
    6. (recordn_value1, recordn_value2,……recordn_valuesn)
    7. ;

    可以看出,每条记录之间都用逗号进行了分隔。

    下面的例子中,对表dept 一次插入两条记录:

    1. mysql> insert into dept values(5,'dept5'),(6,'dept6');
    2. Query OK, 2 rows affected (0.04 sec)
    3. Records: 2 Duplicates: 0 Warnings: 0
    4. mysql> select * from dept;
    5. +--------+----------+
    6. | deptno | deptname |
    7. +--------+----------+
    8. | 1 | tech |
    9. | 2 | sale |
    10. | 5 | fin |
    11. | 5 | dept5 |
    12. | 6 | dept6 |
    13. +--------+----------+
    14. 5 rows in set (0.00 sec)

    这个特性可以使得MySQL 在插入大量记录时,节省很多的网络开销,大大提高插入效率。

  2. 更新记录

    对于表里的记录值,可以通过update 命令进行更改,语法如下:

    1. UPDATE tablename SET field1=value1field2.=value2,……fieldn=valuen [WHERE CONDITION]

    例如,将表emp 中ename 为“lisa”的薪水(sal)从3000 更改为4000:

    1. mysql> update emp set sal=4000 where ename='lisa';
    2. Query OK, 1 row affected (0.00 sec)
    3. Rows matched: 1 Changed: 1 Warnings: 0

    查看结果:

    1. mysql> select * from emp;
    2. +-------+------------+---------+--------+
    3. | ename | hiredate | sal | deptno |
    4. +-------+------------+---------+--------+
    5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    6. | lisa | 2003-02-01 | 3000.00 | 2 |
    7. | dony | NULL | 1000.00 | NULL |
    8. +-------+------------+---------+--------+
    9. 3 rows in set (0.00 sec)
    10. mysql> update emp set sal=4000 where ename='lisa';
    11. Query OK, 1 row affected (0.00 sec)
    12. Rows matched: 1 Changed: 1 Warnings: 0
    13. mysql> select * from emp;
    14. +-------+------------+---------+--------+
    15. | ename | hiredate | sal | deptno |
    16. +-------+------------+---------+--------+
    17. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    18. | lisa | 2003-02-01 | 4000.00 | 2 |
    19. | dony | NULL | 1000.00 | NULL |
    20. +-------+------------+---------+--------+
    21. 3 rows in set (0.00 sec)

    在MySQL 中,update 命令可以同时更新多个表中数据,语法如下:

    1. UPDATE t1,t2tn set t1.field1=expr1,tn.fieldn=exprn [WHERE CONDITION]
  3. 删除记录

    如果记录不再需要,可以用delete 命令进行删除,语法如下:

    1. DELETE FROM tablename [WHERE CONDITION]

    例如,在emp 中将ename 为‘dony’的记录全部删除,命令如下:

    1. mysql> delete from emp where ename='dony';
    2. Query OK, 1 row affected (0.00 sec)

    在MySQL 中可以一次删除多个表的数据,语法如下:

    1. DELETE t1,t2tn FROM t1,t2tn [WHERE CONDITION]

    如果from 后面的表名用别名,则delete 后面的也要用相应的别名,否则会提示语法错误。

    在下例中,将表emp 和dept 中deptno 为3 的记录同时都删除:

    1. mysql> select * from emp;
    2. 41
    3. +--------+------------+---------+--------+
    4. | ename | hiredate | sal | deptno |
    5. +--------+------------+---------+--------+
    6. | zzx | 2000-01-01 | 100.00 | 1 |
    7. | lisa | 2003-02-01 | 200.00 | 2 |
    8. | bjguan | 2004-04-02 | 100.00 | 1 |
    9. | bzshen | 2005-04-01 | 300.00 | 3 |
    10. | dony | 2005-02-05 | 2000.00 | 4 |
    11. +--------+------------+---------+--------+
    12. 5 rows in set (0.00 sec)
    13. mysql> select * from dept;
    14. +--------+----------+
    15. | deptno | deptname |
    16. +--------+----------+
    17. | 1 | tech |
    18. | 2 | sale |
    19. | 3 | hr |
    20. | 5 | fin |
    21. +--------+----------+
    22. 4 rows in set (0.00 sec)
    23. mysql> delete a,b from emp a,dept b where a.deptno=b.deptno and a.deptno=3;
    24. Query OK, 2 rows affected (0.04 sec)
    25. mysql>
    26. mysql>
    27. mysql> select * from emp;
    28. +--------+------------+---------+--------+
    29. | ename | hiredate | sal | deptno |
    30. +--------+------------+---------+--------+
    31. | zzx | 2000-01-01 | 100.00 | 1 |
    32. | lisa | 2003-02-01 | 200.00 | 2 |
    33. | bjguan | 2004-04-02 | 100.00 | 1 |
    34. | dony | 2005-02-05 | 2000.00 | 4 |
    35. +--------+------------+---------+--------+
    36. 4 rows in set (0.00 sec)
    37. mysql> select * from dept;
    38. +--------+----------+
    39. | deptno | deptname |
    40. +--------+----------+
    41. | 1 | tech |
    42. | 2 | sale |
    43. | 5 | fin |
    44. 42
    45. +--------+----------+
    46. 3 rows in set (0.00 sec)
  4. 查询记录

    数据插入到数据库中后,就可以用SELECT 命令进行各种各样的查询,使得输出的结果符合

    我们的要求。由于SELECT 的语法很复杂,所有这里只介绍最基本的语法:

    1. SELECT * FROM tablename [WHERE CONDITION]

    查询最简单的方式是将记录全部选出,在下面的例子中,将表emp 中的记录全部查询出来:

    1. mysql> select * from emp;
    2. +--------+------------+---------+--------+
    3. | ename | hiredate | sal | deptno |
    4. +--------+------------+---------+--------+
    5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    6. | lisa | 2003-02-01 | 4000.00 | 2 |
    7. | bjguan | 2004-04-02 | 5000.00 | 3 |
    8. +--------+------------+---------+--------+
    9. 3 rows in set (0.00 sec)

    其中“*”表示要将所有的记录都选出来,也可以用逗号分割的所有字段来代替,例如,以

    下两个查询是等价的:

    1. mysql> select * from emp;
    2. +--------+------------+---------+--------+
    3. | ename | hiredate | sal | deptno |
    4. +--------+------------+---------+--------+
    5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    6. | lisa | 2003-02-01 | 4000.00 | 2 |
    7. | bjguan | 2004-04-02 | 5000.00 | 3 |
    8. +--------+------------+---------+--------+
    9. 3 rows in set (0.00 sec)
    1. mysql> select ename,hiredate,sal,deptno from emp;
    2. +--------+------------+---------+--------+
    3. | ename | hiredate | sal | deptno |
    4. +--------+------------+---------+--------+
    5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    6. | lisa | 2003-02-01 | 4000.00 | 2 |
    7. | bjguan | 2004-04-02 | 5000.00 | 3 |
    8. +--------+------------+---------+--------+
    9. 3 rows in set (0.00 sec)

    “*”的好处是当需要查询所有字段信息时候,查询语句很简单,但是要只查询部分字段的

    时候,必须要将字段一个一个列出来。

    上例中已经介绍了查询全部记录的语法,但是在实际应用中,用户还会遇到各种各样的查询

    要求,下面将分别介绍。

    • 查看不重复的记录

      有时需要将表中的记录去掉重复后显示出来,可以用distinct 关键字来实现:

      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. +--------+------------+---------+--------+
      9. 3 rows in set (0.00 sec)
      10. mysql> select distinct deptno from emp;
      11. +--------+
      12. | deptno |
      13. +--------+
      14. | 1 |
      15. | 2 |
      16. +--------+
      17. 2 rows in set (0.00 sec)
    • 条件查询

      在很多情况下,用户并不需要查询所有的记录,而只是需要根据限定条件来查询一部分数据,

      用where 关键字可以来实现这样的操作。

      例如,需要查询所有deptno为1的记录:

      1. mysql> select * from emp where deptno=1;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | bjguan | 2004-04-02 | 5000.00 | 1 |
      7. +--------+------------+---------+--------+
      8. 2 rows in set (0.00 sec)

      结果集中将符合条件的记录列出来。上面的例子中,where 后面的条件是一个字段的‘=’

      比较,除了‘=’外,还可以使用>、<、>=、<=、!=等比较运算符;多个条件之间还可以使

      用or、and 等逻辑运算符进行多条件联合查询,运算符会在以后章节中详细讲解。

      以下是一个使用多字段条件查询的例子:

      1. mysql> select * from emp where deptno=1 and sal<3000;
      2. +-------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +-------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. +-------+------------+---------+--------+
      7. 1 row in set (0.01 sec)
    • 排序和限制

      我们经常会有这样的需求,取出按照某个字段进行排序后的记录结果集,这就用到了数据库

      的排序操作,用关键字ORDER BY 来实现,语法如下:

      1. SELECT * FROM tablename [WHERE CONDITION] [ORDER BY field1 [DESC|ASC] field2
      2. [DESC|ASC],……fieldn [DESC|ASC]]

      其中,DESC 和ASC 是排序顺序关键字,DESC 表示按照字段进行降序排列,ASC 则表示升序

      排列,如果不写此关键字默认是升序排列。ORDER BY 后面可以跟多个不同的排序字段,并

      且每个排序字段可以有不同的排序顺序。

      例如,把emp 表中的记录按照工资高低进行显示:


      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. +--------+------------+---------+--------+
      10. 4 rows in set (0.00 sec)
      11. mysql> select *from emp order by sal;
      12. +--------+------------+---------+--------+
      13. | ename | hiredate | sal | deptno |
      14. +--------+------------+---------+--------+
      15. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      16. | bzshen | 2005-04-01 | 3000.00 | 3 |
      17. | lisa | 2003-02-01 | 4000.00 | 2 |
      18. | bjguan | 2004-04-02 | 5000.00 | 1 |
      19. +--------+------------+---------+--------+
      20. 4 rows in set (0.00 sec)

      如果排序字段的值一样,则值相同的字段按照第二个排序字段进行排序,以此类推。如果只

      有一个排序字段,则这些字段相同的记录将会无序排列。

      例如,把emp 表中的记录按照部门编号deptno 字段排序:

      1. mysql> select *from emp order by deptno;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | bjguan | 2004-04-02 | 5000.00 | 1 |
      7. | lisa | 2003-02-01 | 4000.00 | 2 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. +--------+------------+---------+--------+
      10. 4 rows in set (0.00 sec)

      对于deptno 相同的前两条记录,如果要按照工资由高到低排序,可以使用以下命令:

      1. mysql> select *from emp order by deptno ,sal desc;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | bjguan | 2004-04-02 | 5000.00 | 1 |
      6. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      7. | lisa | 2003-02-01 | 4000.00 | 2 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. +--------+------------+---------+--------+
      10. 4 rows in set (0.00 sec)

      对于排序后的记录,如果希望只显示一部分,而不是全部,这时,就可以使用LIMIT 关键字

      来实现,LIMIT 的语法如下:

      1. SELECT ……[LIMIT offset_start,row_count]

      其中offset_start 表示记录的起始偏移量,row_count 表示显示的行数。

      在默认情况下,起始偏移量为0,只需要写记录行数就可以,这时候,显示的实际就是前n

      条记录,看下面例子:

      例如,显示emp 表中按照sal 排序后的前3 条记录:

      1. mysql> select *from emp order by sal limit 3;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | bzshen | 2005-04-01 | 3000.00 | 3 |
      7. | lisa | 2003-02-01 | 4000.00 | 2 |
      8. +--------+------------+---------+--------+
      9. 3 rows in set (0.00 sec)

      如果要显示emp 表中按照sal 排序后从第二条记录开始,显示3 条记录:

      1. mysql> select *from emp order by sal limit 1,3;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | bzshen | 2005-04-01 | 3000.00 | 3 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. +--------+------------+---------+--------+
      9. 3 rows in set (0.00 sec)

      limit 经常和order by 一起配合使用来进行记录的分页显示。

      PS:limit 属于MySQL 扩展SQL92 后的语法,在其他数据库上并不能通用。

    • 聚合

      很多情况下,我们需要进行一些汇总操作,比如统计整个公司的人数或者统计每个部门的人数,这个时就要用到SQL 的聚合操作。

      聚合操作的语法如下:

      1. SELECT [field1,field2,……fieldn] fun_name
      2. FROM tablename
      3. [WHERE where_contition]
      4. [GROUP BY field1,field2,……fieldn
      5. [WITH ROLLUP]]
      6. [HAVING where_contition]

      对其参数进行以下说明:

      • fun_name 表示要做的聚合操作,也就是聚合函数,常用的有sum(求和)、count(*)(记

        录数)、max(最大值)、min(最小值)。
      • GROUP BY 关键字表示要进行分类聚合的字段,比如要按照部门分类统计员工数量,部门

        就应该写在group by 后面。
      • WITH ROLLUP 是可选语法,表明是否对分类聚合后的结果进行再汇总。
      • HAVING 关键字表示对分类后的结果再进行条件的过滤。

      PS:having 和where 的区别在于having 是对聚合后的结果进行条件的过滤,而where 是在聚合前就对记录进行过滤,如果逻辑允许,我们尽可能用where 先过滤记录,这样因为结果集减小,将对聚合的效率大大提高,最后再根据逻辑看是否用having 进行再过滤。

      例如:要emp表中统计公司的总人数:

      1. mysql> select *from emp order by sal limit 1,3;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | bzshen | 2005-04-01 | 3000.00 | 3 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. +--------+------------+---------+--------+
      9. 3 rows in set (0.00 sec)
      10. mysql> select count(*) from emp;
      11. +----------+
      12. | count(*) |
      13. +----------+
      14. | 4 |
      15. +----------+
      16. 1 row in set (0.26 sec)
      17. mysql> select count(1) from emp;
      18. +----------+
      19. | count(1) |
      20. +----------+
      21. | 4 |
      22. +----------+
      23. 1 row in set (0.00 sec)

      在此基础上,要统计各个部门的人数:

      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. +--------+------------+---------+--------+
      10. 4 rows in set (0.00 sec)
      11. mysql> select deptno,count(1) from emp group by deptno;
      12. +--------+----------+
      13. | deptno | count(1) |
      14. +--------+----------+
      15. | 1 | 2 |
      16. | 2 | 1 |
      17. | 3 | 1 |
      18. +--------+----------+
      19. 3 rows in set (0.00 sec)

      更细一些,既要统计各部门人数,又要统计总人数:

      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. +--------+------------+---------+--------+
      10. 4 rows in set (0.00 sec)
      11. mysql> select deptno,count(1) from emp group by deptno with rollup;
      12. +--------+----------+
      13. | deptno | count(1) |
      14. +--------+----------+
      15. | 1 | 2 |
      16. | 2 | 1 |
      17. | 3 | 1 |
      18. | NULL | 4 |
      19. +--------+----------+
      20. 4 rows in set (0.00 sec)

      统计人数大于1 人的部门:

      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. +--------+------------+---------+--------+
      10. 4 rows in set (0.00 sec)
      11. mysql> select deptno,count(1) from emp group by deptno having count(1)> 1;
      12. +--------+----------+
      13. | deptno | count(1) |
      14. +--------+----------+
      15. | 1 | 2 |
      16. +--------+----------+
      17. 1 row in set (0.00 sec)

      最后统计公司所有员工的薪水总额、最高和最低薪水:

      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. +--------+------------+---------+--------+
      10. 4 rows in set (0.00 sec)
      11. mysql> select sum(sal),max(sal),min(sal) from emp;
      12. +----------+----------+----------+
      13. | sum(sal) | max(sal) | min(sal) |
      14. +----------+----------+----------+
      15. | 14000.00 | 5000.00 | 2000.00 |
      16. +----------+----------+----------+
      17. 1 row in set (0.00 sec)
    • 表连接

      当需要同时显示多个表中的字段时,就可以用表连接来实现这样的功能。

      从大类上分,表连接分为内连接和外连接,它们之间的最主要区别是內连接仅选出两张表中互相匹配的记录,而外连接会选出其他不匹配的记录。我们最常用的是内连接。

      例如,查询出所有雇员的名字和所在部门名称,因为雇员名称和部门分别存放在表emp 和

      dept 中,因此,需要使用表连接来进行查询:

      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. +--------+------------+---------+--------+
      10. 4 rows in set (0.00 sec)
      11. mysql> select * from dept;
      12. +--------+----------+
      13. | deptno | deptname |
      14. +--------+----------+
      15. | 1 | tech |
      16. | 2 | sale |
      17. | 3 | hr |
      18. +--------+----------+
      19. 3 rows in set (0.00 sec)
      20. mysql> select ename,deptname from emp,dept where emp.deptno=dept.deptno;
      21. +--------+----------+
      22. | ename | deptname |
      23. +--------+----------+
      24. | zzx1 | tech |
      25. | lisa | sale |
      26. | bjguan | tech |
      27. | bzshen | hr |
      28. +--------+----------+
      29. 4 rows in set (0.00 sec)

      外连接又分为左连接和右连接,具体定义如下:

      • 左连接:包含所有的左边表中的记录甚至是右边表中没有和它匹配的记录
      • 右连接:包含所有的右边表中的记录甚至是左边表中没有和它匹配的记录

      例如,查询emp中所有用户名和所在部门名称

      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. | dony | 2005-02-05 | 2000.00 | 4 |
      10. +--------+------------+---------+--------+
      11. 5 rows in set (0.00 sec)
      12. mysql> select * from dept;
      13. +--------+----------+
      14. | deptno | deptname |
      15. +--------+----------+
      16. | 1 | tech |
      17. | 2 | sale |
      18. | 3 | hr |
      19. +--------+----------+
      20. 3 rows in set (0.00 sec)
      21. mysql> select ename,deptname from emp left join dept on emp.deptno=dept.deptno;
      22. +--------+----------+
      23. | ename | deptname |
      24. +--------+----------+
      25. | zzx1 | tech |
      26. | bjguan | tech |
      27. | lisa | sale |
      28. | bzshen | hr |
      29. | dony | NULL |
      30. +--------+----------+
      31. 5 rows in set (0.00 sec)

      比较这个查询和上例中的查询,都是查询用户名和部门名,两者的区别在于本例中列出了所

      有的用户名,即使有的用户名(dony)并不存在合法的部门名称(部门号为4,在dept 中

      没有这个部门);而上例中仅仅列出了存在合法部门的用户名和部门名称。

      右连接和左连接类似,两者之间可以互相转化,例如,上面的例子可以改写为如下的右连接:

      1. mysql> select ename,deptname from dept right join emp on dept.deptno=emp.deptno;
      2. +--------+----------+
      3. | ename | deptname |
      4. +--------+----------+
      5. | zzx1 | tech |
      6. | bjguan | tech |
      7. | lisa | sale |
      8. | bzshen | hr |
      9. | dony | NULL |
      10. +--------+----------+
      11. 5 rows in set (0.27 sec)
    • 子查询

      某些情况下,当我们查询的时候,需要的条件是另外一个select语句的结果,这个时候,就 要用到子查询。用于子查询的关键字主要包括 in、not in、=、!=、exists、not exists 等。 例如,从 emp表中查询出所有部门在 dept 表中的所有记录:

      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |

    | lisa | 2003-02-01 | 4000.00 | 2 |

    | bjguan | 2004-04-02 | 5000.00 | 1 |

    | bzshen | 2005-04-01 | 3000.00 | 3 |

    | dony | 2005-02-05 | 2000.00 | 4 |

    +--------+------------+---------+--------+

    5 rows in set (0.00 sec)

    mysql> select* from dept;

    +--------+----------+

    | deptno | deptname |

    +--------+----------+

    | 1 | tech |

    | 2 | sale |

    | 3 | hr |

    | 5 | fin |

    +--------+----------+

    4 rows in set (0.00 sec)

    mysql> select* from emp where deptno in (select deptno from dept);

    +--------+------------+---------+--------+

    | ename | hiredate | sal | deptno |

    +--------+------------+---------+--------+

    | zzx1 | 2000-01-01 | 2000.00 | 1 |

    | bjguan | 2004-04-02 | 5000.00 | 1 |

    | lisa | 2003-02-01 | 4000.00 | 2 |

    | bzshen | 2005-04-01 | 3000.00 | 3 |

    +--------+------------+---------+--------+

    4 rows in set (0.00 sec)


    1. 如果子查询记录数唯一,还可以用=代替in
    2. ```shell
    3. mysql> select * from emp where deptno = (select deptno from dept limit 2);
    4. ERROR 1242 (21000): Subquery returns more than 1 row
    5. mysql> select * from emp where deptno = (select deptno from dept limit 1);
    6. +--------+------------+---------+--------+
    7. | ename | hiredate | sal | deptno |
    8. +--------+------------+---------+--------+
    9. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    10. | bjguan | 2004-04-02 | 5000.00 | 1 |
    11. +--------+------------+---------+--------+
    12. 2 rows in set (0.00 sec)

    某些情况下,子查询可以转化为表连接,例如:

    1. mysql> select* from emp;
    2. +--------+------------+---------+--------+
    3. | ename | hiredate | sal | deptno |
    4. +--------+------------+---------+--------+
    5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    6. | lisa | 2003-02-01 | 4000.00 | 2 |
    7. | bjguan | 2004-04-02 | 5000.00 | 1 |
    8. | bzshen | 2005-04-01 | 3000.00 | 3 |
    9. | dony | 2005-02-05 | 2000.00 | 4 |
    10. +--------+------------+---------+--------+
    11. 5 rows in set (0.00 sec)
    12. mysql> select *from dept;
    13. +--------+----------+
    14. | deptno | deptname |
    15. +--------+----------+
    16. | 1 | tech |
    17. | 2 | sale |
    18. | 3 | hr |
    19. | 5 | fin |
    20. +--------+----------+
    21. 4 rows in set (0.00 sec)
    22. mysql> select *from emp where deptno in (select deptno from dept);
    23. +--------+------------+---------+--------+
    24. | ename | hiredate | sal | deptno |
    25. +--------+------------+---------+--------+
    26. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    27. | bjguan | 2004-04-02 | 5000.00 | 1 |
    28. | lisa | 2003-02-01 | 4000.00 | 2 |
    29. | bzshen | 2005-04-01 | 3000.00 | 3 |
    30. +--------+------------+---------+--------+
    31. 4 rows in set (0.00 sec)
    32. # 转换为表连接后
    33. mysql> select emp.* from emp,dept where emp.deptno = dept.deptno;
    34. +--------+------------+---------+--------+
    35. | ename | hiredate | sal | deptno |
    36. +--------+------------+---------+--------+
    37. | zzx1 | 2000-01-01 | 2000.00 | 1 |
    38. | bjguan | 2004-04-02 | 5000.00 | 1 |
    39. | lisa | 2003-02-01 | 4000.00 | 2 |
    40. | bzshen | 2005-04-01 | 3000.00 | 3 |
    41. +--------+------------+---------+--------+
    42. 4 rows in set (0.00 sec)

    注意:子查询和表连接之间的转换主要应用在两个方面:

    • MySQL 4.1 以前的版本不支持子查询,需要用表连接来实现子查询的功能

    • 表连接在很多情况下用于优化子查询

    • 记录联合

      我们经常会碰到这样的应用,将两个表的数据按照一定的查询条件查询出来后,将结果合并到一起显示出来,这个时候,就需要用union和union all 关键字来实现这样的功能,具体语法如下:

      1. SELECT * FROM t1
      2. UNION|UNION ALL
      3. SELECT * FROM t2
      4. ……
      5. UNION|UNION ALL
      6. SELECT * FROM tn;

      UNION 和 UNION ALL 的主要区别是 UNION ALL 是把结果集直接合并在一起,而 UNION 是将 UNION ALL 后的结果进行一次 DISTINCT,去除重复记录后的结果。 来看下面例子,将 emp和 dept 表中的部门编号的集合显示出来:

      1. mysql> select * from emp;
      2. +--------+------------+---------+--------+
      3. | ename | hiredate | sal | deptno |
      4. +--------+------------+---------+--------+
      5. | zzx1 | 2000-01-01 | 2000.00 | 1 |
      6. | lisa | 2003-02-01 | 4000.00 | 2 |
      7. | bjguan | 2004-04-02 | 5000.00 | 1 |
      8. | bzshen | 2005-04-01 | 3000.00 | 3 |
      9. | dony | 2005-02-05 | 2000.00 | 4 |
      10. +--------+------------+---------+--------+
      11. 5 rows in set (0.00 sec)
      12. mysql> select *from dept;
      13. +--------+----------+
      14. | deptno | deptname |
      15. +--------+----------+
      16. | 1 | tech |
      17. | 2 | sale |
      18. | 3 | hr |
      19. | 5 | fin |
      20. +--------+----------+
      21. 4 rows in set (0.00 sec)
      22. # 联合所有(存在重复)
      23. mysql> select deptno from emp
      24. -> union all
      25. -> select deptno from dept;
      26. +--------+
      27. | deptno |
      28. +--------+
      29. | 1 |
      30. | 2 |
      31. | 1 |
      32. | 3 |
      33. | 4 |
      34. | 1 |
      35. | 2 |
      36. | 3 |
      37. | 5 |
      38. +--------+
      39. 9 rows in set (0.00 sec)

      如果希望将结果去掉重复记录后显示:

      1. # 去掉重复记录
      2. mysql> select deptno from emp
      3. -> union
      4. -> select deptno from dept;
      5. +--------+
      6. | deptno |
      7. +--------+
      8. | 1 |
      9. | 2 |
      10. | 3 |
      11. | 4 |
      12. | 5 |
      13. +--------+
      14. 5 rows in set (0.00 sec)

MySQL操作之DML的更多相关文章

  1. 学习笔记:MySQL操作初步

    对数据库的操作:SQL语言 一:SQL:Structured Query Language,结构化查询语言! 二:DDL:Data Definition Language,数据定义语言 三:DML:D ...

  2. Mysql操作初级

    Mysql操作初级 本节内容 数据库概述 数据库安装 数据库操作 数据表操作 表内容操作 1.数据库概述 数据库管理系统叫做DBMS 1.什么是数据库 ? 答:数据的仓库,如:在ATM的示例中我们创建 ...

  3. python学习道路(day12note)(mysql操作,python链接mysql,redis)

    1,针对mysql操作 SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpass'); 设置密码 update user set password ...

  4. 数据操作语言DML与运算符

    数据操作语言DML(添加,修改,删除) 1.添加数据 insert into insert into 表名 (字段列表) values (值列表),值列表要和字段列表按顺序匹配. insert int ...

  5. ecshop的Mysql操作类

    摘要,这是直接摘抄的ecshop的mysql操作类:不过他这里的缓存是用的文件缓存,我们如果想直接使用,可以替换成memcache的或者redis的! <?php /** * ECSHOP MY ...

  6. shell执行mysql操作

    http://ully.iteye.com/blog/1226494 http://www.jb51.net/article/55207.htm shell执行mysql操作 mysql  -hhos ...

  7. mysql操作类库--摘抄

    <!--?php /** +---------------------------------- * MySQL操作类库 +---------------------------------- ...

  8. 第一篇:Mysql操作初级

    Mysql操作初级   Mysql操作初级 本节内容 数据库概述 数据库安装 数据库操作 数据表操作 表内容操作 1.数据库概述 数据库管理系统叫做DBMS 1.什么是数据库 ? 答:数据的仓库,如: ...

  9. Mysql 操作手册

    mysql操作手册 版本:5.6.16mysql linux安装基本步骤:#rpm -e --nodeps mysql-lib-5.1.*#rpm -ivh mysql-server#rpm -ivh ...

随机推荐

  1. java用JSONObject生成json

    Json在前后台传输中,是使用最多的一种数据类型.json生成的方法有很多,自己只是很皮毛的知道点,用的时候,难免会蒙.现在整理下 第一种: import net.sf.json.JSONArray; ...

  2. python、js实现WGS84、高德(火星)、百度坐标转换

    在日常工作学习中常会涉及到WGS84.高德(火星/谷歌).百度三种空间坐标系的坐标转换,本文将通过python.js两种语言实现坐标系的转换. 坐标系说明: wgs84:为一种大地坐标系,也是目前广泛 ...

  3. JS中的数组创建,初始化

    JS中没有专门的数组类型.但是可以在程序中利用预定义的Array对象及其方法来使用数组. 在JS中有三种创建数组的方法: var arr = new Array(1,2,3,4); var arr = ...

  4. Django 单元测试笔记

    引言 关于单元测试的基本知识这里不再讲述,简单一句话:单元测试是用一段代码去测试另一段代码.最常用的框架是unittest,这是python的单元测试框架,而django单元测试框架test.Test ...

  5. 「NOIP2016」蚯蚓

    传送门 Luogu 解题思路 很容易想到用一个堆去维护,但是复杂度是 \(O((n+m)\log(n+m))\) 的,显然过不了 \(7e6\). 其实这题有一个性质: 先被切开的蚯蚓,得到的两条新蚯 ...

  6. Linux 笔记:文件名

    文件名 Linux 系统区分英文字符的大小写.比如,myfile, Myfile 和 myFILE表示的是三个不同的文件.同样,用户密码和登录名也需要区分大小写(这里沿用了Unix 和 C 语言的命名 ...

  7. CSS样式的引入&区别&权重&CSS层叠性&CSS样式的来源

    CSS样式的引入: 内部样式: 内部样式:写在当前页面style标签中的样式 内联样式:写在style属性中的样式 外部样式: link标签引入的CSS文件 @import引入的CSS文件,需要写在c ...

  8. Latin-1字符集

    ISO Latin-1字符集是Unicode字符集的一个子集,对应于IE4+中Unicode字符指令表的前256个条目.下面表格中详细提供了每个字符及字符的十进制编码和HTML已命名实体.其中Unic ...

  9. 电源适配器DC插头规格

    电源适配器 DC 插头的内径外径规格有 (单位为 MM) :2.0*0.72.35*0.72.35*1.12.5*0.73.5*1.13.5*1.354.0*1.75.5*2.15.5*2.54.75 ...

  10. centos610最小安装之后 后续设置

    1.网络配置 centos选择最小桌面(如果不用到类似Oracle需要用到桌面的软件,则操作系统安装最小化安装)安装之后 查看网络配置如下: 截图显示网络并未启用. 2.开启网络设置 cd /etc/ ...