本文整理了SQL基础语法分类总结表,包含9大核心知识点:
1. 基础查询(SELECT/别名);
2. 条件查询(WHERE数值/字符/日期比较);
3. 范围查询(BETWEEN/IN);
4. 模糊查询(LIKE通配符);
5. 空值处理(IS NULL/NVL);
6. 组合条件(AND/OR/NOT优先级);
7. 排序(ORDER BY单/多字段);
8. 执行顺序(WHERE→SELECT→ORDER BY);
9. 万能表DUAL应用。
通过分类表格和示例代码,系统梳理了SQL查询的核心语法要点,便于学习者快速查阅和复习。
总结梳理老师的课堂笔记,重点是使用表格分类总结提到的sql,方便学生复习和学习
以下是根据您的课堂笔记整理的SQL知识分类总结表格,涵盖基础查询、条件筛选、范围匹配、模糊查询、空值处理、组合条件、排序及万能表等内容,便于学生快速复习和查阅。
一、基础查询与别名
| 类别 | 语法 | 示例 |
|---|---|---|
| 查询指定列 | SELECT 列1, 列2 FROM 表名; | SELECT ENAME, SAL FROM EMP; |
| 查询所有列 | SELECT * FROM 表名; | SELECT * FROM EMP; |
| 列别名 | 列名 AS 别名或列名 别名 | SELECT SAL AS 薪资 FROM EMP; |
| 表别名 | 表名 别名 | SELECT e.ENAME FROM EMP e; |
二、条件查询(WHERE)
| 类别 | 运算符 | 示例 |
|---|---|---|
| 数值比较 | =, >, <, >=, <=, <>, != | WHERE SAL > 1000 |
| 字符串比较 | =(需单引号,区分大小写) | WHERE JOB = 'CLERK' |
| 日期比较 | TO_CHAR(日期,'格式')或TO_DATE(字符串,'格式') | WHERE TO_CHAR(HIREDATE,'YYYY') = 1981 |
三、日期处理函数
| 函数 | 说明 | 示例 |
|---|---|---|
TO_CHAR(日期,'格式') | 日期 → 字符串 | TO_CHAR(HIREDATE,'YYYY-MM')→'1981-05' |
TO_DATE(字符串,'格式') | 字符串 → 日期 | TO_DATE('19810501','YYYYMMDD') |
SYSDATE | 当前系统时间 | SELECT SYSDATE FROM DUAL; |
日期格式:
YYYY年,MM月,DD日,HH24小时,MI分钟,SS秒
四、范围查询
| 语法 | 含义 | 示例 |
|---|---|---|
BETWEEN M AND N | [M, N] 闭区间 | WHERE SAL BETWEEN 800 AND 1600 |
NOT BETWEEN M AND N | 不在区间内 | WHERE SAL NOT BETWEEN 1000 AND 3000 |
IN (值1, 值2, ...) | 在集合中 | WHERE DEPTNO IN (10, 20) |
NOT IN (...) | 不在集合中 | WHERE JOB NOT IN ('SALESMAN','MANAGER') |
五、模糊查询(LIKE)
| 通配符 | 含义 | 示例 |
|---|---|---|
% | 匹配0个或多个字符 | WHERE ENAME LIKE 'S%'(S开头) |
_ | 匹配1个字符 | WHERE ENAME LIKE '_L%'(第二位是L) |
NOT LIKE | 反向模糊匹配 | WHERE ENAME NOT LIKE '%K%' |
ESCAPE '\' | 转义通配符(如%或_) | WHERE ENAME LIKE '%\%%' ESCAPE '\' |
六、空值处理(NULL)
| 语法/函数 | 说明 | 示例 |
|---|---|---|
IS NULL | 判断为空 | WHERE COMM IS NULL |
IS NOT NULL | 判断非空 | WHERE MGR IS NOT NULL |
NVL(字段, 缺省值) | 空值替换 | SAL + NVL(COMM, 0) |
注意:
NULL = NULL返回False,必须用IS NULL0不是空值,有占位符。
NULL 参与排序的时候默认是最大值。
七、组合条件(AND / OR / NOT)
| 运算符 | 优先级 | 说明 |
|---|---|---|
NOT | 最高 | 取反 |
AND | 中等 | 同时满足 |
OR | 最低 | 满足其一即可 |
示例:
WHERE DEPTNO = 20 AND JOB = 'MANAGER' OR DEPTNO = 30 AND JOB = 'SALESMAN'等价于:(DEPTNO = 20 AND JOB = 'MANAGER') OR (DEPTNO = 30 AND JOB = 'SALESMAN')
八、排序(ORDER BY)
| 语法 | 说明 | 示例 |
|---|---|---|
ORDER BY 字段 ASC | 升序(默认,可省略) | ORDER BY ENAME |
ORDER BY 字段 DESC | 降序 | ORDER BY SAL DESC |
| 多字段排序 | 先按第一字段,再按第二字段 | ORDER BY DEPTNO, SAL DESC |
| NULL 值排序 | 默认作为最大值 | ORDER BY COMM DESC NULLS LAST |
可以在
ORDER BY中使用列别名,例如ORDER BY 月薪 DESC
九、查询执行顺序(逻辑理解)
text
FROM 表名 WHERE 行级筛选 SELECT 列投影 ORDER BY 排序
示例中
SAL + NVL(COMM,0) > 1500是在WHERE中执行,别名月薪只能在ORDER BY中使用。
十、万能表 DUAL
| 用途 | 示例 |
|---|---|
| 查询常量 | SELECT 1 FROM DUAL; |
| 系统时间 | SELECT SYSDATE FROM DUAL; |
| 无需表数据的计算 | SELECT 3*7 FROM DUAL; |
DUAL这个概念是Oracle独有的,不过其他数据库也有各自的实现方式来达到相同的目的。可以把
DUAL理解成一个由Oracle数据库自动创建的、只有一行一列的"万能小表"。Oracle中的 DUAL
本质:属于 SYS 用户的一张真实存在的物理表,但所有用户都可以直接使用。
结构:只有一个叫
DUMMY的列,类型是VARCHAR2(1),里面只存放了一行数据,值为X。设计目的:为了满足 SQL 的语法要求(
SELECT语句必须跟一个FROM子句),提供一个做简单计算或查询系统变量(如SYSDATE)的"占位符"。
其他数据库的替代方案
就像 "可口可乐" 是一个特定品牌名,而其他品牌叫 "可乐" 一样。虽然很多数据库没有叫DUAL的表,但都用各自的语法实现了同样的功能。
| 数据库 | 实现方式 | 示例写法 |
|---|---|---|
| Oracle | 使用系统内置的DUAL表 | SELECT SYSDATE FROM DUAL; |
| MySQL | 不强制使用FROM,可直接查询但为了兼容也接受 DUAL语法 | SELECT NOW();(也支持 SELECT NOW() FROM DUAL;) |
| PostgreSQL | 不强制使用FROM,可直接查询 | SELECT CURRENT_TIMESTAMP; |
| SQL Server | 不强制使用FROM,可直接查询 | SELECT GETDATE(); |
| DB2 | 使用SYSIBM.DUAL系统表 | SELECT CURRENT DATE FROM SYSIBM.DUAL; |
| SQLite | 不强制使用FROM,可直接查询 | SELECT DATE('now'); |
可以看到,除了 Oracle 和个别数据库,像 MySQL、PostgreSQL、SQL Server 等,已经不需要特意用一张表来充当"占位符"了**,直接写SELECT语句就可以。
总结
| 特性 | Oracle | 其他主流数据库 |
|---|---|---|
是否需要DUAL | 是,语法强制要求 | 否,可以直接SELECT |
DUAL的本质 | 一张物理存在的虚拟表 | 一个为了方便迁移而设计的兼容性语法 |
不过,在日常学习和工作中,查到的大部分网络资料都是基于Oracle体系的,所以在学习阶段了解并掌握DUAL的用法还是很有必要的。
整理所有的sql示例
以下是根据您的课堂笔记整理的所有SQL示例代码汇总,按学习顺序分类,每条示例均配有说明,方便复习和练习。
一、基础查询与别名
sql
-- 查询指定列 SELECT ENAME, SAL FROM EMP; -- 查询所有列 SELECT * FROM EMP; -- 列别名(AS可省略) SELECT ENAME AS 姓名, SAL 薪资 FROM EMP; -- 表别名 SELECT e.ENAME, e.SAL FROM EMP e;
二、条件查询(WHERE)
sql
-- 数值筛选:薪资超过1000 SELECT ENAME, SAL FROM EMP WHERE SAL > 1000; -- 数值筛选:薪资不低于3000 SELECT * FROM EMP WHERE SAL >= 3000; -- 字符筛选:文员 SELECT ENAME, SAL FROM EMP WHERE JOB = 'CLERK'; -- 字符筛选:排除销售 SELECT * FROM EMP WHERE JOB <> 'SALESMAN'; -- 练习1:不是20号部门 SELECT ENAME, SAL, DEPTNO FROM EMP WHERE DEPTNO <> 20; -- 练习2:员工SCOTT SELECT * FROM EMP WHERE ENAME = 'SCOTT';
三、日期筛选
sql
-- 1981年入职(TO_CHAR方式) SELECT * FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYY') = 1981; -- 1981年5月之前入职(TO_CHAR方式) SELECT ENAME, HIREDATE, SAL FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYYMM') < 198105; -- 1981年5月之前入职(TO_DATE方式) SELECT ENAME, HIREDATE, SAL FROM EMP WHERE HIREDATE < TO_DATE('19810501', 'YYYYMMDD'); -- 练习1:1982年之后入职(TO_CHAR) SELECT * FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYY') > 1982; -- 练习1:1982年之后入职(TO_DATE) SELECT * FROM EMP WHERE HIREDATE > TO_DATE('19821231', 'YYYYMMDD'); -- 练习2:1981年2月入职(TO_CHAR) SELECT ENAME, HIREDATE, SAL FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYYMM') = 198102; -- 练习2:1981年2月入职(BETWEEN) SELECT ENAME, HIREDATE, SAL FROM EMP WHERE HIREDATE BETWEEN TO_DATE('19810201', 'YYYYMMDD') AND TO_DATE('19810228', 'YYYYMMDD');四、范围筛选(BETWEEN / IN)
sql
-- BETWEEN:薪资800-1600 SELECT * FROM EMP WHERE SAL BETWEEN 800 AND 1600; -- BETWEEN:1981年1-3月入职 SELECT * FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYYMM') BETWEEN 198101 AND 198103; -- IN:10或20号部门 SELECT * FROM EMP WHERE DEPTNO IN (10, 20); -- IN:指定年月入职 SELECT ENAME, SAL, HIREDATE FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYYMM') IN (198102, 198201, 198705); -- NOT BETWEEN:薪资不在1000-3000 SELECT * FROM EMP WHERE SAL NOT BETWEEN 1000 AND 3000; -- NOT IN:排除指定岗位 SELECT ENAME, JOB, SAL FROM EMP WHERE JOB NOT IN ('SALESMAN', 'MANAGER', 'CLERK'); -- 练习1:薪资1000-3000 SELECT ENAME, SAL FROM EMP WHERE SAL BETWEEN 1000 AND 3000; -- 练习2:排除指定年月 SELECT * FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYY-MM') NOT IN ('1981-02', '1982-01', '1980-12');五、模糊查询(LIKE)
sql
-- S开头 SELECT * FROM EMP WHERE ENAME LIKE 'S%'; -- 第二位是L SELECT * FROM EMP WHERE ENAME LIKE '_L%'; -- 5位长度 SELECT * FROM EMP WHERE ENAME LIKE '_____'; -- 最少6位长度 SELECT * FROM EMP WHERE ENAME LIKE '______%'; -- 倒数第二位是E SELECT * FROM EMP WHERE ENAME LIKE '%E_'; -- 包含S SELECT * FROM EMP WHERE ENAME LIKE '%S%'; -- 反向模糊:不包含K SELECT * FROM EMP WHERE ENAME NOT LIKE '%K%'; -- 反向模糊:倒数第二位不是E SELECT * FROM EMP WHERE ENAME NOT LIKE '%E_'; -- 转义匹配%号 SELECT * FROM EMP WHERE ENAME LIKE '%\%%' ESCAPE '\'; -- 练习1:包含J SELECT * FROM EMP WHERE ENAME LIKE '%J%'; -- 练习2:倒数第三位是N SELECT * FROM EMP WHERE ENAME LIKE '%N__'; -- 练习3:最后一位不是T SELECT * FROM EMP WHERE ENAME NOT LIKE '%T';
六、空值筛选(IS NULL / NVL)
sql
-- 没有佣金(IS NULL) SELECT * FROM EMP WHERE COMM IS NULL; -- 有领导(IS NOT NULL) SELECT * FROM EMP WHERE MGR IS NOT NULL; -- 错误写法:COMM = NULL(返回空) SELECT * FROM EMP WHERE COMM = NULL; -- 月薪计算(NVL处理空值) SELECT ENAME, SAL, COMM, SAL + NVL(COMM, 0) AS 月薪 FROM EMP; -- 练习1:有佣金的员工 SELECT ENAME, JOB, SAL, COMM FROM EMP WHERE COMM IS NOT NULL; -- 练习2:有领导,计算月薪和年薪 SELECT ENAME, SAL, COMM, SAL + NVL(COMM, 0) AS 月薪, (SAL + NVL(COMM, 0)) * 12 AS 年薪 FROM EMP WHERE MGR IS NOT NULL;
七、组合条件(AND / OR / NOT)
sql
-- 20号部门经理 + 30号部门销售 SELECT * FROM EMP WHERE DEPTNO = 20 AND JOB = 'MANAGER' OR DEPTNO = 30 AND JOB = 'SALESMAN'; -- 排除20号 + 姓名5位 + 薪资>1000 SELECT * FROM EMP WHERE NOT DEPTNO = 20 AND ENAME LIKE '_____' AND SAL > 1000; -- 1981或1982入职,名字不包含J,不是10号部门 SELECT * FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYY') = 1981 OR TO_CHAR(HIREDATE, 'YYYY') = 1982 AND ENAME NOT LIKE '%J%' AND DEPTNO != 10; -- 薪资>1000 且 名字不是5位长度 SELECT * FROM EMP WHERE SAL > 1000 AND NOT ENAME LIKE '_____'; -- 练习1:20号部门,薪资1000-3000 SELECT * FROM EMP WHERE DEPTNO = 20 AND SAL BETWEEN 1000 AND 3000; -- 练习2:1981年薪资≥1200 或 1982年1月后无佣金 SELECT * FROM EMP WHERE (TO_CHAR(HIREDATE, 'YYYY') = 1981 AND SAL >= 1200) OR (TO_CHAR(HIREDATE, 'YYYYMM') > 198201 AND COMM IS NULL);
八、排序(ORDER BY)
sql
-- 单字段升序(ASC省略) SELECT ENAME, SAL FROM EMP ORDER BY ENAME; -- 单字段降序 SELECT ENAME, SAL FROM EMP ORDER BY SAL DESC; -- 多字段排序:先部门升序,再月薪降序 SELECT ENAME AS 姓名, SAL AS 薪资, COMM AS 佣金, SAL + NVL(COMM, 0) AS 月薪, DEPTNO AS 部门 FROM EMP WHERE DEPTNO = 20 OR (DEPTNO = 30 AND JOB = 'SALESMAN') ORDER BY DEPTNO ASC, SAL + NVL(COMM, 0) DESC; -- 姓名升序 + 薪资降序 SELECT ENAME, SAL, COMM, SAL + NVL(COMM, 0) FROM EMP ORDER BY ENAME, SAL DESC; -- NULL作为最大值(默认) SELECT * FROM EMP ORDER BY COMM DESC; -- 空值放在最后 SELECT * FROM EMP ORDER BY COMM DESC NULLS LAST; -- 空值放在最前 SELECT * FROM EMP ORDER BY COMM NULLS FIRST; -- 筛选月薪>1500后排序 SELECT ENAME, DEPTNO, SAL, COMM, SAL + NVL(COMM, 0) AS 月薪 FROM EMP WHERE SAL + NVL(COMM, 0) > 1500 ORDER BY DEPTNO, 月薪 DESC; -- 练习1:多部门组合排序 SELECT * FROM EMP WHERE (DEPTNO = 10 AND JOB = 'CLERK') OR (DEPTNO = 20 AND JOB = 'MANAGER') OR DEPTNO = 30 ORDER BY DEPTNO, SAL DESC; -- 练习2:1981或1982年后入职,按月薪降序 SELECT ENAME, SAL, COMM, SAL + NVL(COMM, 0) AS 月薪 FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYY') = 1981 OR TO_CHAR(HIREDATE, 'YYYY') > 1982 ORDER BY 月薪 DESC;
九、万能表 DUAL
sql
-- 查询当前系统时间 SELECT SYSDATE FROM DUAL; -- 查询常量 SELECT 1 AS A1 FROM DUAL WHERE 1 = 1; -- 查询字符串 SELECT 'ABC' FROM DUAL; -- 计算表达式 SELECT 3 * 7 FROM DUAL;
附录:常用函数速查
| 函数 | 作用 | 示例 |
|---|---|---|
TO_CHAR(日期, 格式) | 日期转字符串 | TO_CHAR(HIREDATE, 'YYYY-MM') |
TO_DATE(字符串, 格式) | 字符串转日期 | TO_DATE('19810501', 'YYYYMMDD') |
NVL(字段, 缺省值) | 空值替换 | NVL(COMM, 0) |
SYSDATE | 当前系统时间 | SYSDATE |
课后作业
desc emp; /* 名称 空值? 类型 -------- -------- ------------ EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER(2) */ select * from emp where ROWNUM <= 20; --7369 SMITH CLERK 7902 17-12月-80 800 20 --7499 ALLEN SALESMAN 7698 20-2月 -81 1600 300 30 --7521 WARD SALESMAN 7698 22-2月 -81 1250 500 30 --7566 JONES MANAGER 7839 02-4月 -81 2975 20 --7654 MARTIN SALESMAN 7698 28-9月 -81 1250 1400 30 --7698 BLAKE MANAGER 7839 01-5月 -81 2850 30 --7782 CLARK MANAGER 7839 09-6月 -81 2450 10 --7788 SCOTT ANALYST 7566 13-7月 -87 3000 20 --7839 KING PRESIDENT 17-11月-81 5000 10 --7844 TURNER SALESMAN 7698 08-9月 -81 1500 0 30 --7876 ADAMS CLERK 7788 13-7月 -87 1100 20 --7900 JAMES CLERK 7698 03-12月-81 950 30 --7902 FORD ANALYST 7566 03-12月-81 3000 20 --7934 MILLER CLERK 7782 23-1月 -82 1300 10 --1.输出员工薪资在 1000到2000之间,且岗位不是销售也不是经理的所有员工信息; select * from EMP where sal between 1000 and 2000 and job not in('MANAGER','SALESMAN'); --2.排除20号部门的经理 以及 30号部门销售,输出其他的所有员工明细信息; SELECT * FROM EMP WHERE NOT (DEPTNO = 20 AND JOB = 'MANAGER') AND NOT (DEPTNO = 30 AND JOB = 'SALESMAN'); --3.输出入职时间在 1982年10月之前的所有员工姓名,入职时间,中文展示; select ename as 姓名, HIREDATE as 入职时间 from EMP where to_char(HIREDATE,'YYYYMM')<198210; --4.输出所有入职时间既不是1981年2月 也不是 1981年5 月 也不是 1982年1月的所有员工信息; select * from EMP where to_char(HIREDATE,'YYYYMM') not in(198102,198105,198201); --5.输出20号部门入职时间在1982年之前以及30号部门入职时间在1985年之前的所有员工信息; select * from EMP where (DEPTNO=20 and to_char(HIREDATE,'YYYY')<1982) or (DEPTNO=30 and to_char(HIREDATE,'YYYY')<1985); --6.输出所有员工姓名是五个字符以及姓名中包含T 的员工姓名,薪资 以及入职时间; select ename,sal,HIREDATE from EMP where ename like '_____' or ename like '%T%'; --7.找出所有员工姓名不包含S且,长度不低于5位长度的员工信息; select * from EMP where ename not like '%S%' and ename like '_____%'; --8.找出所有存在上级领导编号的员工,并且计算他们的年薪是多少,输出 员工姓名 领导编号 薪资 佣金 年薪; select ename,MGR,sal,comm,(sal+nvl(comm,0))*12 as 年薪 from EMP where MGR is not Null; --9.输出所有佣金低于500(为空默认为0,也是低于500)的所有员工信息; select * from EMP where nvl(comm,0) < 500; --10.输出每个员工的姓名,薪资 佣金 月薪(薪资+佣金) 年薪 按照姓名的升序 年薪的降序排序; --两个排序字段之间必须用逗号隔开 select ename,sal,comm,(sal+nvl(comm,0)) as 月薪,(sal+nvl(comm,0))*12 as 年薪 from EMP order by ename asc,"年薪" desc; --11.筛选1981年之后入职的所有员工,输出他们的姓名 月薪 佣金 年薪 部门编号, --按照部门编号升序,月薪的降序排序; select ename,(sal+nvl(comm,0)) as 月薪,comm,(sal+nvl(comm,0))*12 as 年薪,DEPTNO from EMP WHERE TO_CHAR(HIREDATE, 'YYYY') > 1981 order by DEPTNO asc,月薪 desc; --12. 筛选30号部门所有销售 以及 20号部门 1985 年之前入职的所有员工,然后输出 他们的 --员工姓名 薪资 佣金 月薪 部门编号 --要求 按照部门编号升序 佣金降序排序,并且 佣金为空的排在最后面。 select ename,sal,comm,(sal+nvl(comm,0)) as 月薪,DEPTNO,hiredate from EMP where (DEPTNO=30 and job='SALESMAN') or (DEPTNO=20 and to_char(hiredate,'YYYY')<1985) ORDER BY DEPTNO ASC, comm DESC NULLS LAST;