【Oracle】Oracle之DQL中WHERE限制条件查询

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只出现一次,所以不会额外返回96WITH TIES只检查最后一行(第5行)是否有重复值,不会检查前面的行。

  • WITH TIES仅针对限制行的最后一行进行处理,不会处理排序中所有重复的数值

假设成绩排名为:100, 100, 99, 98, 97, 97, 96, 95, 94, 93

  1. FETCH FIRST 5 ONLY

    • 结果:100, 100, 99, 98, 97

    • 解释:严格返回前5行

  2. 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后有如下输出

相关推荐
luis的妙妙屋4 小时前
主流数据库数据类型对比分析
数据库
斌味代码4 小时前
Shell 性能监控:指标采集、告警规则与可视化大盘设计
运维
XDHCOM4 小时前
ORA-00054资源忙故障修复,远程处理Oracle报错解决方案,数据库锁超时NOWAIT指定问题排查
数据库·oracle
22信通小白4 小时前
USRP初学者使用手册(基础配置及bug记录)——Linux+Clion(单台X310收发)
linux·运维·c++·5g·bug·信息与通信
网络安全许木4 小时前
自学渗透测试第14天(信息收集进阶与指纹识别)
linux·网络安全·渗透测试
q21030633724 小时前
初学Access(具体示例)
数据库
xlq223224 小时前
40.线程控制
linux
l1t5 小时前
DeepSeek总结的PostgreSQL使用 RDTSC 降低 EXPLAIN ANALYZE 的计时开销
数据库·postgresql
lagrahhn5 小时前
Oracle中各个c版本介绍
数据库·oracle