共计 7018 个字符,预计需要花费 18 分钟才能阅读完成。
五、限定查询和排序显示
5.1、限定查询
5.1.1 认识限定查询
- 例如 :如果一张表中有 100w 条数据,一旦执行了“SELECT * FROM 表”语句之后,则将在屏幕上显示表中全部数据行的记录,这样既不方便浏览,也可能造成死机的问题,所以此时就必须对查询的结果进行筛选,只选出对自己有用的数据即可,那么就可以通过 WHERE 指定查询的筛选条件。
- 这么多条数据一起显示肯定是无法浏览的。另外,如果数据量显示的过多,那么有可能出现死机的问题。所以下面首先来观察数据量大对于查询显示会存在什么问题。
- 在进行 Oracle 数据库安装的时候已经安装了样本方案数据库,所以现在必须将容器由 CDB 切换到 PDB 之中。
范例 :以 nolog 的方式打开 sqlplus (在命令行终端)
sqlplus /nolog
范例 :使用 sys 管理员登录
CONN sys/chagne_on_install AS SYSDBA;
范例 :切换到 PDB 之中
ALTER SESSION SET CONTAINER=pdbmldn;
范例 :打开 PDB
ALTER DATABASE pdbmldn OPEN;
范例 :查看 sh 用户的数据表内容
SELECT COUNT(*) FROM sh.sales;
- 现在这张表中存在有 9w 多条记录,如果直接发出如下指令:
SELECT * FROM sh.sales;
- 现在显示结果一直不停变换,无法查看,按 Ctrl+C 停止。所以现在数据量一大,那么是不可能这样直接查看全部数据的,所以全部数据行的显示根本就不可能使用。很多时候往往需要针对所需要的数据进行筛选,而筛选就是限定查询的功能。
- 现在连接到 c##scott 用户:
conn c##scott/tiger;
5.1.2 限定查询语法:
SELECT [DISTINCT] * | 列名称 [AS] [列别名], 列名称 [AS] [列别名],...
FROM 表名称 [表别名]
[WHERE 条件 ( s)];
-
在这个语法之中,就是比之前的语法多了一个 WHERE 子句,在 WHERE 子句之中可以设置一系列的过滤条件。而这些条件可以设置多个,那么这多个条件之间就可以利用逻辑运算进行连接。
-
逻辑运算符共有以下三种:
- 与(AND):连接多个条件,多个条件同时满足时才返回 TRUE,有一个条件不满足结果就是 FALSE;
- 或(OR):连接多个条件,多个条件之中只要有一个返回 TRUE,结果就是 TRUE,如果多个条件返回的都是 FALSE,结果才是 FALSE;
- 非(NOT):求反操作,可以将 TRUE 变 FALSE,FALSE 变 TRUE。
逻辑真值表:
NO. | 条件 x | 条件 y | x AND y | x OR y | NOT x |
---|---|---|---|---|---|
1 | TRUE | TRUE | TRUE | TRUE | FALSE |
2 | TRUE | NULL | NULL | TRUE | FALSE |
3 | TRUE | FALSE | FALSE | TRUE | FALSE |
4 | NULL | TRUE | NULL | TRUE | NULL |
5 | NULL | NULL | NULL | NULL | NULL |
6 | NULL | FALSE | FALSE | NULL | NULL |
7 | FALSE | TRUE | FALSE | TRUE | TRUE |
8 | FALSE | NULL | FALSE | NULL | TRUE |
9 | FALSE | FALSE | FALSE | TRUE | TRUE |
范例 :统计出基本工资高出 1500 的全部雇员信息
- 现在的查询已经出现了一个条件要求,所以在这种情况下就必须使用 WHERE 子句进行条件的设置。
SELECT * FROM emp WHERE sal>1500;
-
现在可以发现并不是所有的数据都显示了,只是部分的数据显示,而且这部分都是满足条件的数据。
- 现在对于 SQL 语法而言,就具备了三个子句:
- 第一步:执行 FROM 子句,来控制数据的来源
- 第二步:执行 WHERE 子句,使用限定符进行数据行的过滤
- 第三步:执行 SELECT 子句,确定要显示的数据列
5.1.3 对数据进行限定查询
- 在之前所使用的“>”是一个关系运算符,在标准 SQL 之中定义了许多的运算符。
- 常用限定运算符:
NO | 运算符 | 符号 | 描述 |
---|---|---|---|
1 | 关系运算符 | >、<、>=、<=、=、!=、<> | 进行大小或相等的比较,其中不等于有两种:!= 和 <> |
2 | 判断 null | IS NULL、IS NOT NULL | 判断某一列的内容是否是 null |
3 | 逻辑运算符 | AND、OR、NOT | AND 表示多个条件必须同时满足,OR 表示只需要有一个条件满足即可,NOT 表示条件取反,即:真变假,假变真 |
4 | 范围查询 | BETWEEN 最小值 AND 最大值 | 在一个指定范围中进行查找,查找结果为:“最小值 <= 内容 <= 最大值” |
5 | 范围查询 | IN | 通过 IN 可以指定一个查询的范围 |
6 | 模糊查询 | LIKE | 可以对指定的字段进行模糊查询 |
5.1.3.1 关系运算符
- 关系运算就是确定大小、相等关系的比较。
范例 :要求查询出所有基本工资小于等于 2000 的全部雇员信息
SELECT *
FORM emp
WHERE sal<=2000;
范例 :根据之前的查询结果发现 SMITH 的工资最低,现在希望可以取得 SMITH 的详细资料。
SELECT *
FORM emp
WHERE ename='SMITH';
范例 :查询出所有办事员(CLERK)的雇员信息
SELECT *
FORM emp
WHERE job='CLERK';
- 但是在使用关系运算符判断字符数据的时候请一定要主要大小写的编写问题。因为 Oracle 是区分大小写的。
范例: 错误的代码
SELECT *
FORM emp
WHERE job='clerk'; // 不会有结果返回
范例 :取得了所有办事员的资料之后,为了和其他职位的雇员对比,现在决定再查询出所有不是办事员的雇员信息。
-
既然现在职位不是办事员,那么肯定使用不等于符号(<>, !=)
- 实现一:
SELECT * FORM emp WHERE job<>'CLERK';
- 实现二:
SELECT * FORM emp WHERE job!='CLERK';
范例 :查询出工资范围在 1500 ~ 3000(都包含)的全部雇员信息
- 现在这个判断是两个条件,而且这两个条件肯定需要同时满足,那么就使用 AND 进行条件的连接
SELECT *
FORM emp
WHERE sal>=1500 AND sal<=3000;
范例 :查询职位是销售,并且基本工资高于 1200 的所有雇员信息
SELECT *
FORM emp
WHERE job='SALESMAN' AND sal>1200;
范例 :查询出 10 部门中的经理或者是 20 部门的业务员的信息
SELECT *
FORM emp
WHERE (deptno=10 AND job='MANAGER') OR (deptno=20 AND job='CLERK');
范例 :查询不是办事员的且基本工资大于 2000 的全部雇员信息
- 实现一:基本实现
SELECT *
FORM emp
WHERE job!='CLERK' AND sal>2000;
SELECT *
FORM emp
WHERE job<>'CLERK' AND sal>2000;
- 实现二:使用 NOT 对条件求反
SELECT *
FORM emp
WHERE NOT(job='CLERK' OR sal<=2000);
5.1.3.2 范围查询
范例 :使用 BETWEEN…AND… 操作符查询工资范围在 1500(含)~ 3000(含)的全部雇员信息
SELECT *
FORM emp
WHERE sal BETWEEN 1500 AND 3000;
范例 :查询���在 1981 年雇佣的全部雇员信息
SELECT *
FORM emp
WHERE hiredate BETWEEN '01- 1 月 -81' AND '31-12 月 -1981';
实际上这里就实现了日期和字符串数据之间的转换操作的功能。
5.1.3.3 null 判断:
-
判断内容是否为 null:IS NULL , IS NOT NULL
- 语法:
-
判断为 NULL:字段 | 值 IS NULL;
-
判断不为 NULL:字段 | 值 IS NOT NULL; (NOT 字段 | 值 IS NULL;)
NULL 是一个未知的数据,所以对于 NULL 的处理,如果直接利用关系运算判断,是不会有结果的
-
范例 :利用 = 进行 NULL 比较
SELECT *
FORM emp
WHERE comm=null AND empno=7369;
- 结果显示没有任何数据返回,因为 NULL 不能使用 = 判断。
范例 :查询出所有领取佣金的雇员的完整信息
-
佣金的字段是 comm,领取佣金的概念就属于佣金不为 null。
- 实现一:直接使用 IS NOT NULL 完成
SELECT * FORM emp WHERE comm IS NOT NULL;
- 实现二:使用 IS NULL 并使用 NOT 求反完成
SELECT * FORM emp WHERE NOT comm IS NULL;
范例 :查询出所有不领取佣金的雇员的完整信息
SELECT *
FORM emp
WHERE comm IS NULL;
范例 :列出所有的不领取奖金的雇员,而且同时要求这些雇员的基本工资大于 2000 的全部雇员信息
SELECT *
FORM emp
WHERE comm IS NULL AND sal > 2000;
范例 :找出不领取佣金或领取的佣金低于 100 的员工
SELECT *
FORM emp
WHERE comm IS NULL OR comm < 100;
范例 :找出收取佣金的员工的不同工作
- 既然现在要找的是职位,那么很有可能出现重复,重复发数据就必须使用 DISTINCT 消除。
SELECT DISTINCT job
FORM emp
WHERE comm IS NOT NULL;
5.1.3.4 列表范围查找:IN,NOT IN
-
所谓的列表范围指的是给了用户固定的几个参考值,只要符合这个值就满足条件。
- 语法:
- 在指定数据范围内:字段 | 值 IN (值, 值,…);
- 不在指定数据范围内:字段 | 值 NOT IN (值, 值,…);
范例 :查询出雇员编号是 7369,7788,7566 的雇员信息
- 那么面对这样的操作,如果此时不使用 IN 判断符就可以利用多个条件并且使用 OR 进行连接。
SELECT *
FORM emp
WHERE empno = 7369 OR empno = 7788 OR empno = 7566;
- 下面使用优秀代码 IN 实现
SELECT *
FORM emp
WHERE empno IN (7369,7788,7566);
范例 :现在查询除了 7369,7788,7566 之外的雇员信息
SELECT *
FORM emp
WHERE empno NOT IN (7369,7788,7566);
-
但是在使用 NOT IN 操作的时候有一点需要注意,关于 NULL 的问题:
- 如果使用的是 IN 操作符判断的范围数据之中包含了 NULL,那么不会影响最终的查询结果。
SELECT * FORM emp WHERE empno IN (7369,7788,null);
- 但是如果使用的是 NOT IN,里面有 NULL,直接的后果就是没有任何数据显示。
SELECT * FORM emp WHERE empno NOT IN (7369,7788,null);
-
使用 NOT IN 或 IN 其目的只是显示部分内容,如果说现在有一列数据不可能为 NULL,并且 NOT IN 里面判断 null 的条件满足了,那么就表示的是查询全部数据。这样就有可能导致取得的数据量过多导致程序死机。
-
所以,NOT IN 中强加了一个限制,不能有 null,有 null 就没有数据,这是一个死限制。
5.1.3.4 模糊查询: LIKE,NOT LIKE
- 语法:
- 满足模糊查询:字段 | 值 LIKE 匹配标记
- 不满足模糊查询:字段 | 值 NOT LIKE 匹配标记
- 如果现在想对查询某一列进行模糊查询,可以使用 LIKE 子句完成,通过 LIKE 可以进行关键字的模糊查询,在 LIKE 子句中有两个通配符:
- 百分号(%):可以匹配任意类型和长度的字符,如果是中文则使用两个百分号(%%)
- 下划线(_):匹配单个任意字符,它常用来限制表达式的字符长度
范例 :查询出雇员姓名是以 S 开头的全部雇员信息
- 证明 S 之后的内容可以是任意的数据,可能是 0 位、1 位或者多位。
SELECT *
FORM emp
WHERE ename LIKE 'S%';
范例 :查询出雇员姓名的第二个字母是 M 的全部雇员信息
- 现在只是第二个字母,那么证明第一个字母可以任意了,所以使用“_”。
SELECT *
FORM emp
WHERE ename LIKE '_M%';
范例 :查询出雇员姓名中任意位置包含字母 F 的雇员信息
- 现在可能是开头,也可能是结尾,或者是在中间,所以就必须考虑到前后都有的问题,那么使用 %。
SELECT *
FORM emp
WHERE ename LIKE '%F%';
范例 :查询雇员姓名长度为 6 或者是超过 6 个的雇员信息。
- 姓名的长度为 6,那么肯定可以写 6 个“_”,如果可以超过 6,就加一个 %。
SELECT *
FORM emp
WHERE ename LIKE '______%';
范例 :查询出雇员基本工资中包含 1 或者是在 81 年雇佣的全部雇员
- 在之前的所有查询之中都是针对于字符数据进行的操作,而对于 LIKE 而言,也可以在数字或者;日期类型上使用。
SELECT *
FORM emp
WHERE sal LIKE '%1%' OR hiredate LIKE (%81%);
- 但是有一点需要提醒的是,如果在设置模糊查询的时候不设置关键字,就表示查询全部,如:
SELECT *
FORM emp
WHERE sal LIKE '%%'
OR hiredate LIKE (%%)
OR ename LIKE '%%'
OR job LIKE '%%';
结果显示全部数据。
范例 :找出部门 10 中所有经理,部门 20 中所有办事员,既不是经理又不是办事员但薪金大于或等于 2000 的所有员工的详细资料,并且要求这些雇员姓名之中含有字母 S 或字母 K。
- 现在存在于以下几个条件:
- 条件一:10 部门的经理
- 条件二:20 部门的办事员
- 条件三:不是经理和办事员,但是薪金大于或等于 2000
- 条件四:以上所有条件满足之后再过滤,包含字母 S 或字母 K
SELECT *
FORM emp
WHERE ((deptno = 10 AND job = 'MANAGER')
OR (deptno = 20 AND job = 'CLERK')
OR (job NOT IN (MANAGER,CLERK) AND sal >= 2000))
AND (ename LIKE '%S% OR ename LIKE'%K%');
- 小结:
- 限定排序主要使用 WHERE 子句,用于对选取的数据进行控制。
- 限定查询主要的运算符:关系运算、BETWEEN…AND、IN、IS NULL、LIKE
5.2、排序显示
5.2.1 认识排序
- 传统数据查询的时候只会按照设置的主键排序。如果现在希望对指定的列进行排序的操作,那么就必须通过 ORDER BY 子句完成控制。
5.2.2 排序语法
SELECT [DISTINCT] * | 列名称 [AS] 列别名, 列名称 [AS] 列别名
FORM 表名称 表别名
[WHERE 条件 (S)]
[ORDER BY 排序的字段 | 列索引序号 ASC | DESC,
排序的字段 2 ASC | DESC ...]...;
- 在 ORDER BY 子句之中可以指定要进行排序的字段,而后字段有两种排序模式:
- 升序:ASC,默认
- 降序:DESC,需要编写的。
- 在所有的子句之中,一定要记住,ORDER BY 子句是放在查询语句的最后一行,是最后一个执行的,它的执行顺序:FROM、WHERE、SELECT、ORDER BY,既然 ORDER BY 在 SELECT 之后执行,那么就表示 ORDER BY 子句可以使用 SELECT 子句之中设置的别名。
范例 :查询雇员的完整信息并且按照基本工资由高到低进行排序
SELECT *
FORM emp
ORDER BY sal DESC;
范例 :修改之前的查询,要求按照基本工资由低到高进行排序
- 实现一:
SELECT *
FORM emp
ORDER BY sal;
- 实现二:
SELECT *
FORM emp
ORDER BY sal ASC;
范例 :查询出所有办事员(CLERK)的详细资料,并且按基本工资由低到高排序
- 现在不再是针对所有的数据进行排序,需要对数据执行筛选,那么就利用 WHERE 子句完成。
SELECT *
FORM emp
WHERE job = 'CLERK'
ORDER BY sal;
范例 :查询所有雇员信息,要求按照基本工资由高到低排序,如果工资相等则按照雇佣日期进行排序,按照由早到晚的顺序
- 现在的排序需要设置两个排序的字段:sal(DESC),hiredate(ASC)
SELECT *
FORM emp
ORDER BY sal DESC,hiredate ASC;
- 显示结果中有点小问题,本程序的语法没有问题,有问题的是在于数据上。因为现在的数据都是后期处理的结果,如果要想正常的观察数据,那么可以将数据库切换到 PDB 中,找到原始的 scott 数据。
- 方法:在 DBA_Connection 中先执行下面两行代码后继续查询
ALTER SESSION SET CONTAINER = pdbmldn;
ALTER DATABASE pdbmldn OPEN;
SELECT *
FROM scott.emp
ORDER BY sal DESC ,hiredate ASC;
- 但是对于排序,除了使用字段之外,也可以设置一个序号,但是此操作不建议使用。
SELECT empno, ename, sal, job
FORM emp
ORDER BY sal DESC;
SELECT empno, ename, sal, job
FORM emp
ORDER BY 3 DESC;
上面两个语句执行效果一样,但个人认为,在编写排序的时候还是建议写上字段,不要用序号,不方便。
-
小结
- SQL 语法:
SELECTL [DISTINCT] * | 列 [AS][别名], 列 [AS][别名],... FROM 表名称 [别名] [WHERE 限定条件 (s)] [ORDER BY 排序字段 [ASC|DESC][, 排序字段 [ASC|DESC]...]];
- 使用 ORDER BY 子句可以对查询结果进行排序,ORDER BY 子句一定要写在所有查询语句的最后。
说明:本学习资料是根据李兴华的 Oracle 开发实战经典整理
: