Oracle版本:19c
一、使用WHERE限制条件查询和数据排序
1.1 限制行数据
-
WHERE子句
-
使用=,<=,BETWEEN,IN,LIKE和NULL条件的比较运算符
-
使用AND,OR和NOT运算符的逻辑条件
数值限制
cpp
-- 对列值为数值的列进行限制
SQL> SELECT employee_id, last_name, job_id, department_id
2 FROM employees
3 WHERE department_id = 90; -- 限制department_id列为90的结果可以输出
EMPLOYEE_ID LAST_NAME JOB_ID DEPARTMENT_ID
----------- ------------------------- ---------- -------------
100 King AD_PRES 90
101 Kochhar AD_VP 90
102 De Haan AD_VP 90
字符串和日期限制
-
字符串和日期值用单引号引起来。
-
字符值区分大小写,日期值区分格式。
-
默认日期显示格式为DD-MON-RR。
DD-MON-RR 是oracle的默认日期显示格式,DD为日期,MON为月份缩写,RR表示两位数年份,并且具有智能推断世纪的功能,能有效解决千年虫问题。
当前年份后两位为00-49时:
-
指定年份00-49 → 当前世纪(如当前2023年,23表示2023年)
-
指定年份50-99 → 下一世纪(如当前2023年,50表示2150年)
当前年份后两位为50-99时:
-
指定年份00-49 → 上一世纪(如当前1999年,08表示2008年)
-
指定年份50-99 → 当前世纪(如当前1999年,98表示1998年)
字符串限制
cpp
-- 通过字符串限制结果的输出
SQL> SELECT last_name, job_id, department_id
2 FROM employees
3 WHERE last_name = 'Whalen';
LAST_NAME JOB_ID DEPARTMENT_ID
------------------------- ---------- -------------
Whalen AD_ASST 10
日期限制
cpp
-- 通过日期限制结果的输出
SELECT last_name
FROM employees
WHERE hire_date = '17-10月-03';

1.2 比较运算符

比较限制行输出
cpp
-- 输出工资小于等于3000的人的姓名和工资
SQL> SELECT last_name, salary
2 FROM employees
3 WHERE salary <= 3000;
LAST_NAME SALARY
------------------------- ----------
Baida 2900
Tobias 2800
Himuro 2600
Colmenares 2500
Mikkilineni 2700
Landry 2400
Markle 2200
Atkinson 2800
Marlow 2500
Olson 2100
Rogers 2900
需要注意的是不等于的表示,可以使用 != 或者 <>
cpp
-- 输出工资不等于3000的人的姓名和工资
SQL> SELECT last_name, salary
2 FROM employees
3 WHERE salary <> 3000;
SQL> SELECT last_name, salary
2 FROM employees
3 WHERE salary != 3000;
LAST_NAME SALARY
------------------------- ----------
King 24000
Kochhar 17000
De Haan 17000
Hunold 9000
Ernst 6000
Austin 4800
Pataballa 4800
Lorentz 4200
Greenberg 12008
Faviet 9000
Chen 8200
-- 输出结果都是一样的
BETWEEN <lower limit> AND <upper limit>
需要注意的是BETWEEN AND表示的是闭区间,等价于 <=upper limit and >=lower limit
cpp
-- 输出工资在2500到3000的人的姓名和工资
SQL> SELECT last_name, salary
2 FROM employees
3 WHERE salary BETWEEN 2500 AND 3000;
LAST_NAME SALARY
------------------------- ----------
Baida 2900
Tobias 2800
Himuro 2600
Colmenares 2500
Mikkilineni 2700
Atkinson 2800
Marlow 2500
Rogers 2900
Seo 2700
Patel 2500
Matos 2600
-- 等价于以下写法
SQL> SELECT last_name, salary
2 FROM employees
3 WHERE salary <= 3000 AND salary >= 2500;
IN (values)
IN (value1,values2)等价于 =value1 or =value2
cpp
-- 输出manager_id等于100或101或102的人的数据
SQL> SELECT employee_id, last_name, salary, manager_id
2 FROM employees
3 WHERE manager_id IN (100,101,102);
EMPLOYEE_ID LAST_NAME SALARY MANAGER_ID
----------- ------------------------- ---------- ----------
101 Kochhar 17000 100
102 De Haan 17000 100
114 Raphaely 11000 100
120 Weiss 8000 100
121 Fripp 8200 100
122 Kaufling 7900 100
123 Vollman 6500 100
124 Mourgos 5800 100
145 Russell 14000 100
146 Partners 13500 100
147 Errazuriz 12000 100
EMPLOYEE_ID LAST_NAME SALARY MANAGER_ID
----------- ------------------------- ---------- ----------
148 Cambrault 11000 100
149 Zlotkey 10500 100
201 Hartstein 13000 100
108 Greenberg 12008 101
200 Whalen 4400 101
203 Mavris 6500 101
204 Baer 10000 101
205 Higgins 12008 101
103 Hunold 9000 102
-- 等价于以下写法
SQL> SELECT employee_id, last_name, salary, manager_id
2 FROM employees
3 WHERE manager_id = 100 OR manager_id = 101 OR manager_id = 102;
LIKE
-
使用LIKE运算符对有效的搜索字符串值执行通配符搜索。
-
搜索条件可以包含文字字符或数字:
-
%表示任意个字符。
-
_表示一个字符
-
可以将两个通配符(%,_)与文字字符结合使用以进行模式匹配:
-
可以使用ESCAPE标识符搜索实际的%和_符号。
-
cpp
-- 输出姓名是大写S开头的人的数据
SQL> SELECT first_name
2 FROM employees
3 WHERE first_name LIKE 'S%';
FIRST_NAME
--------------------
Sundar
Shelli
Sarah
Shelley
Steven
Sundita
Steven
Susan
Samuel
Sarath
Stephen
FIRST_NAME
--------------------
Sigal
Shanta
13 rows selected.
-- 组合通配符
-- 输出名字第二个字符为小写o的人的数据
SQL> SELECT last_name
2 FROM employees
3 WHERE last_name LIKE '_o%';
LAST_NAME
-------------------------
Colmenares
Doran
Fox
Johnson
Jones
Kochhar
Lorentz
Mourgos
Popp
Rogers
Tobias
LAST_NAME
-------------------------
Vollman
12 rows selected.
-- 输出名字带有小写p的人的数据
SQL> SELECT last_name
2 FROM employees
3 WHERE last_name LIKE '%p%';
LAST_NAME
-------------------------
Fripp
Popp
Raphaely
-- 搜索实际的下划线_
-- 需要使用转义字符
SELECT job_id, job_title
FROM jobs
WHERE job_id LIKE '%\_%' ESCAPE '\';
-- ESCAPE '\':声明反斜杠 \ 是转义符。
-- \ _:表示我要查找的是真正的下划线,而不是"任意一个字符"。
-- %(前后的):依然是通配符,表示下划线前后可以有任意内容。
IS NULL
使用IS NULL运算符测试是否为NULL
cpp
-- 输出manager_id为NULL的人的姓名
SQL> SELECT last_name, manager_id
2 FROM employees
3 WHERE manager_id IS NULL;
LAST_NAME MANAGER_ID
------------------------- ----------
King
1.3 逻辑运算符

AND
AND要求所有组件条件都为真,判定才为真,一假即假
cpp
-- 输出工资大于10000并且job_id带有MAN字符的人的数据
SQL> SELECT employee_id, last_name, job_id, salary
2 FROM employees
3 WHERE salary >= 10000
4 AND job_id LIKE '%MAN%';
EMPLOYEE_ID LAST_NAME JOB_ID SALARY
----------- ------------------------- ---------- ----------
114 Raphaely PU_MAN 11000
145 Russell SA_MAN 14000
146 Partners SA_MAN 13500
147 Errazuriz SA_MAN 12000
148 Cambrault SA_MAN 11000
149 Zlotkey SA_MAN 10500
201 Hartstein MK_MAN 13000
7 rows selected.
OR
OR运算符要求一个条件为真即判定为真,一真即真
cpp
-- 输出工资大于10000或者job_id带有MAN字符的人的数据
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary >= 10000
OR job_id LIKE '%MAN%' ;
EMPLOYEE_ID LAST_NAME JOB_ID SALARY
----------- ------------------------- ---------- ----------
146 Partners SA_MAN 13500
147 Errazuriz SA_MAN 12000
148 Cambrault SA_MAN 11000
149 Zlotkey SA_MAN 10500
150 Tucker SA_REP 10000
156 King SA_REP 10000
162 Vishney SA_REP 10500
168 Ozer SA_REP 11500
169 Bloom SA_REP 10000
174 Abel SA_REP 11000
201 Hartstein MK_MAN 13000
NOT
NOT代表对判定结果取反
cpp
-- 输出job_id不是'IT_PROG', 'ST_CLERK', 'SA_REP'的人的数据
SELECT last_name, job_id
FROM employees
WHERE job_id NOT IN ('IT_PROG', 'ST_CLERK', 'SA_REP') ;
LAST_NAME JOB_ID
------------------------- ----------
Taylor SH_CLERK
Tobias PU_CLERK
Urman FI_ACCOUNT
Vollman ST_MAN
Walsh SH_CLERK
Weiss ST_MAN
Whalen AD_ASST
Zlotkey SA_MAN
二、表达式中运算符的优先级规则

可以使用括号覆盖优先级规则
三、使用ORDER BY子句对行进行排序
使用ORDER BY子句对检索到的行进行排序:
-
ASC: 升序排序, 默认
-
DESC: 降序排序
cpp
-- 按照日期升序排序输出
SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY hire_date ;
LAST_NAME JOB_ID DEPARTMENT_ID HIRE_DATE
------------------------- ---------- ------------- -------------------
De Haan AD_VP 90 2001-01-13 00:00:00
Gietz AC_ACCOUNT 110 2002-06-07 00:00:00
Baer PR_REP 70 2002-06-07 00:00:00
Mavris HR_REP 40 2002-06-07 00:00:00
Higgins AC_MGR 110 2002-06-07 00:00:00
Faviet FI_ACCOUNT 100 2002-08-16 00:00:00
Greenberg FI_MGR 100 2002-08-17 00:00:00
Raphaely PU_MAN 30 2002-12-07 00:00:00
Kaufling ST_MAN 50 2003-05-01 00:00:00
Khoo PU_CLERK 30 2003-05-18 00:00:00
King AD_PRES 90 2003-06-17 00:00:00
-- 按照department_id降序排序
SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY department_id DESC ;
LAST_NAME JOB_ID DEPARTMENT_ID HIRE_DATE
------------------------- ---------- ------------- -------------------
Khoo PU_CLERK 30 2003-05-18 00:00:00
Colmenares PU_CLERK 30 2007-08-10 00:00:00
Tobias PU_CLERK 30 2005-07-24 00:00:00
Himuro PU_CLERK 30 2006-11-15 00:00:00
Baida PU_CLERK 30 2005-12-24 00:00:00
Fay MK_REP 20 2005-08-17 00:00:00
Hartstein MK_MAN 20 2004-02-17 00:00:00
Whalen AD_ASST 10 2003-09-17 00:00:00
-- 通过列的数字位置进行排序
-- 这里第三列数据为department_id,则按照department_id进行升序排序
SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY 3; -- 列数字不能超过实际存在的列数,这里是4列
LAST_NAME JOB_ID DEPARTMENT_ID HIRE_DATE
------------------------- ---------- ------------- -------------------
Whalen AD_ASST 10 2003-09-17 00:00:00
Hartstein MK_MAN 20 2004-02-17 00:00:00
Fay MK_REP 20 2005-08-17 00:00:00
Raphaely PU_MAN 30 2002-12-07 00:00:00
Khoo PU_CLERK 30 2003-05-18 00:00:00
Baida PU_CLERK 30 2005-12-24 00:00:00
Tobias PU_CLERK 30 2005-07-24 00:00:00
Himuro PU_CLERK 30 2006-11-15 00:00:00
Colmenares PU_CLERK 30 2007-08-10 00:00:00
Mavris HR_REP 40 2002-06-07 00:00:00
Weiss ST_MAN 50 2004-07-18 00:00:00
-- 按多列排序
-- 这是先按照department_id升序排序,然后再按照工资降序排序
-- 实际意义:按照部门从高到低排序员工的工资
SELECT last_name, department_id, salary
FROM employees
ORDER BY department_id, salary DESC;
LAST_NAME DEPARTMENT_ID SALARY
------------------------- ------------- ----------
Tuvault 80 7000
Sewall 80 7000
Lee 80 6800
Ande 80 6400
Johnson 80 6200
Banda 80 6200
Kumar 80 6100
King 90 24000
Kochhar 90 17000
De Haan 90 17000
Greenberg 100 12008
四、查询中的SQL行限制子句
可以使用row_limiting_clause来限制查询返回的行。
可以使用此子句实现Top-N报告。
可以使用FETCH FIRST关键字指定要返回的行数或行数百分比。
可以使用OFFSET关键字指定返回的行以完整结果集的第一行之后的一行开始。
WITH TIES关键字包含其他行,这些行具有与行受限结果集的最后一行相同的排序键。 (必须在查询中指定ORDER BY。)
需要注意的是,WITH TIES 仅会处理行限制中最后一行出现重复值的情况,比如以下情况假设10人成绩排名为:100, 100, 99, 98, 97, 96, 95, 94, 93, 92(已按ORDER BY grade DESC排序)
1、FETCH FIRST 5 ONLY 的行为
-
返回结果:100, 100, 99, 98, 97
-
解释:严格返回前5行,不考虑是否有相同值
-
关键点:第5行是97,没有重复值(在您的数据中,97只出现一次)
2、FETCH FIRST 5 WITH TIES 的行为
-
返回结果:100, 100, 99, 98, 97
-
解释 :返回前5行,并检查**第5行(97)**是否有重复值
-
关键点 :在我的数据中,97只出现一次,所以不会额外返回96 。
WITH TIES只检查最后一行(第5行)是否有重复值,不会检查前面的行。 -
WITH TIES仅针对限制行的最后一行进行处理,不会处理排序中所有重复的数值
假设成绩排名为:100, 100, 99, 98, 97, 97, 96, 95, 94, 93
-
FETCH FIRST 5 ONLY:-
结果:100, 100, 99, 98, 97
-
解释:严格返回前5行
-
-
FETCH FIRST 5 WITH TIES:-
结果:100, 100, 99, 98, 97, 97
-
解释:第5行是97,而97有重复值(第6行也是97),所以额外返回了第6行
-
cpp
-- 语法
SELECT ...
FROM ...
[ WHERE ... ]
[ ORDER BY ... ]
[OFFSET offset { ROW | ROWS }]
[FETCH { FIRST | NEXT } [{ row_count | percent PERCENT }] { ROW | ROWS }
{ ONLY | WITH TIES }]
示例
cpp
-- 返回前5行数据
SELECT employee_id, first_name
FROM employees
ORDER BY employee_id
FETCH FIRST 5 ROWS ONLY;
EMPLOYEE_ID FIRST_NAME
----------- --------------------
100 Steven
101 Neena
102 Lex
103 Alexander
104 Bruce
-- 返回第6到10行数据
SELECT employee_id, first_name
FROM employees
ORDER BY employee_id
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY; # 可以理解为按5行分页,从下一页开始输出5行
EMPLOYEE_ID FIRST_NAME
----------- --------------------
105 David
106 Valli
107 Diana
108 Nancy
109 Daniel
五、替代变量
使用替代变量可以:
- 临时存储带有单(&)和双(&&)替换的值
使用替代变量补充以下内容:
-
WHERE条件
-
ORDER BY子句
-
列表达式
-
表名
-
整个SELECT语句
使用单&的替换变量
单&变量在每次执行的时候都会需要用户输入
cpp
-- 使用以"&"为前缀的变量来提示用户输入值:
SELECT employee_id, last_name, salary, department_id
FROM employees
WHERE employee_id = &employee_num ;
Enter value for employee_num: 100 -- 需要让用户输入employee_num作为WHERE判断条件
old 3: WHERE employee_id = &employee_num
new 3: WHERE employee_id = 100
EMPLOYEE_ID LAST_NAME SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
100 King 24000 90
-- 替换变量为字符或者日期,需要使用单引号将单&变量括住,不然会报错
SELECT last_name, department_id, salary*12
FROM employees
WHERE job_id = '&job_title' ;
Enter value for job_title: FI_MGR
old 3: WHERE job_id = '&job_title'
new 3: WHERE job_id = 'FI_MGR'
LAST_NAME DEPARTMENT_ID SALARY*12
------------------------- ------------- ----------
Greenberg 100 144096
-- 指定列名称,表达式和文本
SELECT employee_id, last_name, job_id,&column_name
FROM employees
WHERE &condition
ORDER BY &order_column ;
-- 需要进行三次输入
Enter value for column_name: salary
old 1: SELECT employee_id, last_name, job_id,&column_name
new 1: SELECT employee_id, last_name, job_id,salary
Enter value for condition: salary > 1500
old 3: WHERE &condition
new 3: WHERE salary > 1500
Enter value for order_column: department_id
old 4: ORDER BY &order_column
new 4: ORDER BY department_id
使用双&的替换变量
双&变量只需要输入一次,后续均会使用第一次输入的值
如果要重复使用变量值而不每次都提示用户,请使用双"&"号:
cpp
SELECT employee_id, last_name, job_id, &&column_name
FROM employees
ORDER BY &column_name ;
-- 只有第一次执行时需要输入
Enter value for column_name: department_id
old 1: SELECT employee_id, last_name, job_id, &&column_name
new 1: SELECT employee_id, last_name, job_id, department_id
old 3: ORDER BY &column_name
new 3: ORDER BY department_id
SELECT employee_id, last_name, job_id, &&column_name
FROM employees
ORDER BY &column_name ;
-- 后续再次执行会直接使用第一次的值,不再需要用户重新输入
六、DEFINE和VERIFY命令
6.1 DEFINE命令
-
使用DEFINE命令创建变量并将其分配给变量。
-
使用UNDEFINE命令删除变量。
cpp
DEFINE employee_num = 200
SELECT employee_id, last_name, salary, department_id
FROM employees
WHERE employee_id = &employee_num ;
old 3: WHERE employee_id = &employee_num
new 3: WHERE employee_id = 200
EMPLOYEE_ID LAST_NAME SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
200 Whalen 4400 10
UNDEFINE employee_num
6.2 VERIFY命令
在SQL Developer用值替换替换变量之前和之后,使用VERIFY命令切换替换变量的显示:
cpp
SET VERIFY ON
SELECT employee_id, last_name, salary
FROM employees
WHERE employee_id = &employee_num;
-- 需要注意的是,在sql developer中想要查看替换变量的信息,需要将上面的命令一起执行,而在sql*plus中默认VERIFY就是开启的
在sql developer中设置VERIFY ON后有如下输出
