MySQL (4) 查询语言

252 阅读5分钟

1. 基础查询

概念: 数据查询语言(DQL),负责查询数据,所有SELECT开头的语句全属于DQL的范围之内。

  • 基本格式:SELECT 字段,字段... FROM 查询范围
  • 注释使用 -- 加一个空格。
    • mysql中可以使用 # 作为注释。
  • 查询全部用 * 替代,但是不建议使用,查询效率低。
    • mysql中的 * 可以直接和其他字段一起展示,但并不建议。
  • 代码语法不区分大小写,建议写成全大写有助于提高效率。
    • 对于mysql来说,表中的值也不区分大小写。
  • 字段可以起别名,用 AS 关键字来标注,也可以省略不写,别名可以使用中文但不建议。
  • 表名可以起别名,不建议使用 AS 标注,对表起别名可以提高查询效率。
  • 字符类型数据用单引号或双引号标注,建议使用单引号。
  • 数字类型数据可以直接进行计算,null值和任何值进行计算结果都为null。

源码: dql/基础查询.sql

SELECT *
FROM EMP;

SELECT ENAME, JOB
FROM EMP;

SELECT ENAME AS EMP_NAME, JOB EMP_JOB
FROM EMP;

SELECT ENAME "EMP_NAME", JOB 'EMP_JOB'
FROM EMP;

SELECT T.ENAME, T.SAL, SAL + 200 TOTAL
FROM EMP T;

SELECT T.ENAME, T.COMM, COMM + 200 TOTAL
FROM EMP T;

2. 查询排序

概念: ORDER BY 关键字可以对结果集进行排序:

  • 格式:ORDER BY 排序字段, 排序字段... 排序规则
    • ASC 代表升序,默认值,可以省略不写。
    • DESC 代表降序。
  • ORDER BY 是对结果集的排序,所以必须要写在语句最后,也是程序最后一步运行的。
  • ORDER BY 不参与任何计算,也不会改变任何一个值。
  • ORDER BY 后可以使用多个字段,按顺序进行分组,用逗号隔开。

源码: dql/查询排序.sql

SELECT JOB, SAL
FROM EMP
ORDER BY SAL;

SELECT JOB, SAL
FROM EMP
ORDER BY SAL DESC;

SELECT SAL, EMPNO
FROM EMP
ORDER BY SAL, EMPNO DESC;

3. 条件查询

概念: WHERE 关键字可以在查询的过程中,逐条进行条件判断:

  • 格式:SELECT * FROM 表名 WHERE 条件
    • 即使多个条件,WHERE 关键字也只能有一个。
    • 条件允许使用 ANDORNOT<>!= 来做逻辑判断。
    • AND 的优先级高于 OR
  • 为了提高效率,筛选过程慢,即筛选量大的条件,要尽量往后放。

源码: dql/条件查询.sql

SELECT *
FROM EMP
WHERE ENAME = 'SMITH';

SELECT ENAME
FROM EMP
WHERE ENAME != 'SMITH';

SELECT ENAME
FROM EMP
WHERE ENAME <> 'SMITH';

SELECT ENAME, SAL
FROM EMP
WHERE SAL + 500 > 2000;

SELECT ENAME, SAL
FROM EMP
WHERE SAL > 2000
  AND SAL <= 3000;

SELECT ENAME, SAL, JOB
FROM EMP
WHERE SAL = 1250
  OR JOB = 'SALESMAN';

4. 模糊查询

概念: LIKE 关键字可以在查询的过程中,逐条进行模糊匹配:

  • 占位符:% 表示随意个数占位,_ 表示只占一位。
  • 可以使用 LIKE ESCAPE 转义字符 来指定转义字符,符号建议使用 \
    • mysql可以直接使用 \ 作为转义字符而不需要使用 ESCAPE 声明。
  • 两个单引号可以表示一个单引号:
    • mysql的 \ 可以直接作用于单引号上。
  • 模糊查询的内容不区分大小写。

脚本: 插入 %张%'李' 为了测试。

INSERT INTO EMP (EMPNO, ENAME)
VALUES (1111, '%张%'),
       (2222, '\'李\'');
COMMIT;

源码: dql/模糊查询.sql

SELECT ENAME
FROM EMP
WHERE ENAME LIKE 'S%';

SELECT ENAME
FROM EMP
WHERE ENAME LIKE '_M%';

SELECT *
FROM EMP
WHERE ENAME LIKE '%''%';

INSERT INTO EMP (EMPNO, ENAME)
VALUES (1111, '%张%'),
       (2222, '\'李\'');
COMMIT;

SELECT ENAME
FROM EMP
WHERE ENAME LIKE '%\%%';

SELECT ENAME
FROM EMP
WHERE ENAME LIKE '%$%%' ESCAPE '$';

SELECT ENAME
FROM EMP
WHERE ENAME LIKE '%\'%';

SELECT ENAME
FROM EMP
WHERE ENAME LIKE '%''%';

5. 分组查询

概念: GROUP BY 关键字可以进行分组,分组查询最终只能得到一列数据。

  • 分组查询 FROM 前的字段只能是 GROUP BY 后出现的字段。
    • mysql中允许出现其他字段,但不建议。
  • 分组查询不忽略null值,即null值也可以独立成为一组。
  • 分组查询可以和 WHERE 一起使用,会先执行 WHERE,再进行 GROUP BY
  • GROUP BY 后可以使用多个字段,按顺序进行分组,用逗号隔开。

源码: dql/分组查询.sql

SELECT JOB
FROM EMP
GROUP BY JOB;

SELECT JOB
FROM EMP
WHERE SAL > 2000
GROUP BY JOB;

SELECT JOB, ENAME
FROM EMP
GROUP BY JOB, ENAME;

6. 子查询

概念: 利用A查询提供一个临时的结果集供B使用,则可以称A为B的子查询:

  • 单行子查询:子查询先独立执行且只执行一次,结果返回一行数据,供B使用。
  • 多行子查询:子查询先独立执行且只执行一次,结果返回多行数据,供B使用。
    • ANY(子查询): 某些信息符合,结果集中是OR的关系,不等式专用。
    • SOME(子查询): 某些信息符合,结果集中是OR的关系,等式专用。
    • ALL(子查询): 全部信息符合,结果集中是AND的关系。
  • 关联子查询:父查询每查询一条数据都需要先进行一次子查询,父子查询互相依靠,子查询无法独立运行。
    • 子查询只要有返回值(不在乎返回值是什么),则父查询输出,否则跳过。
    • 关联子查询的关键字是:EXISTS(子查询)NOT EXISTS(子查询)

源码: dql/子查询.sql

SELECT ENAME, SAL
FROM EMP
WHERE SAL > (SELECT SAL FROM EMP WHERE ENAME = 'MARTIN');

SELECT ENAME, SAL
FROM EMP
WHERE SAL > ANY (SELECT SAL FROM EMP WHERE DEPTNO = 10);

SELECT ENAME, SAL
FROM EMP
WHERE SAL = SOME (SELECT SAL FROM EMP WHERE DEPTNO = 10);

SELECT ENAME, SAL
FROM EMP
WHERE SAL > ALL (SELECT SAL FROM EMP WHERE DEPTNO = 20);

SELECT DEPTNO, DNAME
FROM DEPT
WHERE EXISTS(SELECT 1 FROM EMP WHERE EMP.DEPTNO = DEPT.DEPTNO);

SELECT DEPTNO, DNAME
FROM DEPT
WHERE NOT EXISTS(SELECT 1 FROM EMP WHERE EMP.DEPTNO = DEPT.DEPTNO);

7. 分页查询

概念: LIMIT 关键字可以进行分页处理:

  • 当数据量很大时,一次性查询结果就会变得很慢,为了提高查询效率,我们可以使用mysql的分页查询功能。
  • 格式:
    • SELECT * FROM 表名 LIMIT N:从第头开始,显示N条。
    • SELECT * FROM 表名 LIMIT M, N:从第M条开始(包括M),显示N条。
  • 优化:如果M值过大,会导致分页效率低,因为mysql需要从0开始进行操作,建议先使用条件查询将数据进行限定,限定到M后再直接 LIMIT N 进行分页,效率会大大提升。

源码: dql/分页查询.sql

SELECT *
FROM EMP
LIMIT 5;

SELECT *
FROM EMP
LIMIT 5, 5;

SELECT *
FROM EMP
LIMIT 100000, 100;

SELECT *
FROM EMP
WHERE EMPNO BETWEEN 1000000 AND 1000100
LIMIT 100;

8. 联表查询

概念: JOIN 关键字可以进行联表查询:

  • 很多时候,我们需要的数据来自于多张表中,这时候我们就需要连表,两表成功相连需要一个联合条件。
  • 格式:
    • SQL92: SELECT * FROM 表A, 表B WHERE 联合条件
    • SQL99: SELECT * FROM 表A JOIN 表B ON 联合条件
  • 内联:INNER JOIN,仅仅显示满足连接条件的信息,INNER 可省略。
  • 左外联:LEFT JOIN,完整显示左侧信息,即使不满足连接条件。
  • 右外联:RIGHT JOIN,完整显示右侧信息,即使不满足连接条件。
  • 自联:将自己的表分成多个部分进行联合。
  • 联表后如果出现相同列名,建议使用表名或表名的别名作为前缀,加以区分。

源码: dql/联表查询.sql

SELECT EMPNO, ENAME, E.DEPTNO, DNAME
FROM EMP E,
     DEPT D
WHERE E.DEPTNO = D.DEPTNO;

SELECT EMPNO, ENAME, E.DEPTNO, DNAME
FROM EMP E
         JOIN DEPT D ON E.DEPTNO = D.DEPTNO;

SELECT EMPNO, ENAME, E.DEPTNO, DNAME
FROM EMP E
         INNER JOIN DEPT D ON E.DEPTNO = D.DEPTNO;

SELECT EMPNO, ENAME, E.DEPTNO, DNAME
FROM EMP E
         LEFT JOIN DEPT D ON E.DEPTNO = D.DEPTNO;

SELECT EMPNO, ENAME, D.DEPTNO, DNAME
FROM EMP E
         RIGHT JOIN DEPT D ON E.DEPTNO = D.DEPTNO;

SELECT XIAO.ENAME, DA.ENAME
FROM EMP XIAO
         JOIN EMP DA ON DA.EMPNO = XIAO.MGR;

9. 集合查询

概念: UNION 关键字可以对两个结果集进行并集查询:

  • 格式:
    • UNION:返回两个结果集的并集,并过滤相同信息。
    • UNION ALL:返回两个结果集的并集,但不过滤相同信息。
  • 参加运算的集合必须有相同的列,如果不相同用null补,而且列的类型必须对应。
  • 并集运算中,null值不进行忽略。

源码: dql/集合查询.sql

(SELECT DEPTNO FROM DEPT)
UNION
(SELECT DEPTNO FROM EMP);

(SELECT DEPTNO FROM DEPT)
UNION ALL
(SELECT DEPTNO FROM EMP);

10. 正则查询

概念: REGEXP 关键字可以进行正则查询。

  • 格式:SELECT * FROM 表名 WHERE 字段 REGEXP '正则表达式模板'

正则表达式符号表 源码: dql/正则查询.sql

SELECT ENAME
FROM EMP
WHERE ENAME REGEXP '^S';

SELECT ENAME
FROM EMP
WHERE ENAME REGEXP 'H$';

SELECT ENAME
FROM EMP
WHERE ENAME REGEXP 'S';

SELECT ENAME
FROM EMP
WHERE ENAME REGEXP '^[AEIOU]|MS$';