- 浏览: 1267306 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
jackhong1108:
你可能只知道Oracle有like,不知道Oracle有其他的 ...
Hive使用regexp,RLIKE需要使用转义字符 -
pktangshao:
a_bun 写道iijjll 写道使用wmsys.wm_con ...
Oracle 列转行函数 Listagg() -
nayouzhenai:
Spring读取properties文件作为环境变量 -
a_bun:
iijjll 写道使用wmsys.wm_concat()函数也 ...
Oracle 列转行函数 Listagg() -
Horse_Chasing:
鼓励鼓励鼓励鼓励鼓励鼓励鼓励鼓励鼓励鼓励
广州面试小结
本文是看了DB2 SQL精粹有感写的Oracle版本,毕竟两个大公司的产品有不同嘛。
说起WITH 语句,除了那些第一次听说WITH 语句的人,大部分人都觉得它是用来做
递归查询的。其实那只是它的一个用途而已,它的本名正如我们标题写的那样,叫做:公共
表表达式(Common Table Expression),从字面理解,大家觉得它是用来干嘛的呢?
其实,它是用来定义临时集合的。
WITH可以定义多个结果集,中间用逗号分隔。
(这种写法更加符合普通思维的逻辑,写出来的代码更加容易理解)
WITH 语句是为复杂的查询为设计的,的确是这样的,下面我们举个复杂的例子,想提高技术的朋友可千万不能错过。考虑下面的情况:
假设现在让你查询一下那些1、学历是硕士或博士2、学历相同,入职年份也相同,但是工资(基本工资+奖金)却比相同条件员工的平均工资低的员工。(哈哈,可能是要涨工资),不知道你听明白问题没有?该怎么查询呢?我们是这样想的:
1、查询学历是硕士或博士的那些员工得到结果集1,如下:
2、根据学历和入职年份分组,求平均工资得到结果集2,如下:
3、以学历和入职年份为条件联合两个结果集,查找工资<平均工资的员工,以下是完整的SQL:
查询结果完全正确,但我们还有改善的空间,在查询结果集2 的时候,我们是从user 表中取得数据的。其实此时结果集1 已经查询出来了,我们完全可以从结果集1 中通过分组得到结果集2,而不用从uer 表中得到结果集2,比较上面和下面的语句你就可以知道我说的是什么意思了!
当你看到这时,如果很好的理解了上面的内容,我相信你会对WITH 语句有了一定的体会。然而WITH 语句能做的还不止这些,下面给大家介绍一下,如何用WITH 语句做递归查询。
那么,现在让你查询一下DB2 的所有文章及评论,怎么办?传统的方法就
很难查询了,这时候递归查询就派上用场了,如下:
运行后,我们发现,结果完全正确,那它到底是怎么运行的呢?下面我们详细讲解一下。
1、首先,语句1 将会执行,它只执行一次,作为循环的起点。得到结果集:DB2
2、接着,将循环执行语句3,这里我们有必要详细介绍一下。
首先语句3 的意图是什么呢?说白了,它就是查找语句1产生结果集(DB2)的下一级,那么在目录树中DB2 的下一级是什么呢?是‘DB2 文章1’和‘DB2 文章2’,并且把查询到的结果集作为下一次循环的起点,然后查询它们的下一级,直到没有下一级为止。
怎么样?还没明白?哈哈,不要紧,我们一步一步来:
首先,语句1 产生结果集:DB2,作为循环的起点,把它和BBS 表关联来查找它的下一级,查询后的结果为:‘DB2 文章1’和‘DB2 文章2’接着,把上次的查询结果(也就是‘DB2 文章1’和‘DB2 文章2’)和BBS 表关联来查找它
们的下一级,查询后的结果为:‘DB2 文章1 的评论1’ 和‘DB2 文章1 的评论2’。然后,在把上次的查询结果(也就是‘DB2 文章1 的评论1’ 和‘DB2 文章1 的评论2’)和BBS 表关联来查找它们的下一级,此时,没有结果返回,循环结束。
3、第三,将执行语句2,将所有的结果集放在一起,最终得到temp 结果集。
4、最后,我们通过语句4 从temp 临时集合中得到我们期望的查询结果。怎么样,这回理解了吧,如果还没有理解,那么我也无能为力了。
需要特别提醒的是
1、一定要注意语句3 的关联条件,否则很容易就写成死循环了。
2、语句2必须是UNION ALL
接下来,如果做如此更改后,再次执行WITH 递归语句
再次执行则会出现以下错误:
ERROR:ORA-32044:执行递归WITH查询时检测到循环
这时候,可以使用CYCLE语句忽略循环导致的错误,如下:
此时我们得到多了一列出来,DUP_IND
(PS.需要注意的是,这个结果和使用CONNECT BY NOCYCLE得到的结果并不一致,ID为1的记录会出现两次。后面会降到CONNECT BY语句的使用)
DUP_IND为’Y’的时候,表示出现了死循环。
同时CYCLE可以判断在在同一叶子上是否出现重复的值。
如果执行:
再次执行带CYCLE的递归查询语句。
也会发现有一个’Y’在上面,因为后面的“DB2 文章1”内容重复了。
但是,如果执行的插入数据语句是:
则不会出现Y。
说起WITH 语句,除了那些第一次听说WITH 语句的人,大部分人都觉得它是用来做
递归查询的。其实那只是它的一个用途而已,它的本名正如我们标题写的那样,叫做:公共
表表达式(Common Table Expression),从字面理解,大家觉得它是用来干嘛的呢?
其实,它是用来定义临时集合的。
WITH TEMP(ID,USER) AS( SELECT ‘01’,’SAM’ FROM DUAL UNION ALL SELECT ‘02’,’MIKE’ FROM DUAL UNION ALL SELECT ‘03’,’TOM’ FROM DUAL UNION ALL SELECT ‘04’,’JANE’ FROM DUAL ) SELECT * FROM TEMP;
WITH可以定义多个结果集,中间用逗号分隔。
(这种写法更加符合普通思维的逻辑,写出来的代码更加容易理解)
WITH 语句是为复杂的查询为设计的,的确是这样的,下面我们举个复杂的例子,想提高技术的朋友可千万不能错过。考虑下面的情况:
CREATE TABLE USER ( NAME VARCHAR(20) NOT NULL,--姓名 DEGREE INTEGER NOT NULL,--学历(1、专科2、本科3、硕士4、博士) STARTWORKDATE date NOT NULL,--入职时间 SALARY1 FLOAT NOT NULL,--基本工资 SALARY2 FLOAT NOT NULL--奖金 );
假设现在让你查询一下那些1、学历是硕士或博士2、学历相同,入职年份也相同,但是工资(基本工资+奖金)却比相同条件员工的平均工资低的员工。(哈哈,可能是要涨工资),不知道你听明白问题没有?该怎么查询呢?我们是这样想的:
1、查询学历是硕士或博士的那些员工得到结果集1,如下:
SELECT NAME,DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, SALARY1+SALARY2 AS SALARY FROM USER WHERE DEGREE IN (3,4);
2、根据学历和入职年份分组,求平均工资得到结果集2,如下:
SELECT DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, AVG(SALARY1+SALARY2) AS AVG_SALARY FROM USER WHERE DEGREE IN (3,4) GROUP BY DEGREE,YEAR(STARTWORKDATE)
3、以学历和入职年份为条件联合两个结果集,查找工资<平均工资的员工,以下是完整的SQL:
WITH TEMP1(NAME,DEGREE,WORDDATE,SALARY) AS ( SELECT NAME,DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, SALARY1+SALARY2 AS SALARY FROM USER WHERE DEGREE IN (3,4) ), TEMP2 (DEGREE,WORDDATE,AVG_SALARY) AS ( SELECT DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, AVG(SALARY1+SALARY2) AS AVG_SALARY FROM USER WHERE DEGREE IN (3,4) GROUP BY DEGREE,YEAR(STARTWORKDATE) ) SELECT NAME FROM TEMP1, TEMP2 WHERE TEMP1.DEGREE=TEMP2.DEGREE AND TEMP1.WORDDATE=TEMP2.WORDDATE AND SALARY<AVG_SALARY;
查询结果完全正确,但我们还有改善的空间,在查询结果集2 的时候,我们是从user 表中取得数据的。其实此时结果集1 已经查询出来了,我们完全可以从结果集1 中通过分组得到结果集2,而不用从uer 表中得到结果集2,比较上面和下面的语句你就可以知道我说的是什么意思了!
WITH TEMP1(NAME,DEGREE,WORDDATE,SALARY) AS ( SELECT NAME,DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, SALARY1+SALARY2 AS SALARY FROM USER WHERE DEGREE IN (3,4) ), TEMP2 (DEGREE,WORDDATE,AVG_SALARY) AS ( SELECT DEGREE,WORDDATE, AVG(SALARY) AS AVG_SALARY FROM TEMP1 GROUP BY DEGREE,WORDDATE ) SELECT NAME FROM TEMP1, TEMP2 WHERE TEMP1.DEGREE=TEMP2.DEGREE AND TEMP1.WORDDATE=TEMP2.WORDDATE AND SALARY<AVG_SALARY;
当你看到这时,如果很好的理解了上面的内容,我相信你会对WITH 语句有了一定的体会。然而WITH 语句能做的还不止这些,下面给大家介绍一下,如何用WITH 语句做递归查询。
CREATE TABLE BBS ( PARENTID INTEGER NOT NULL, ID INTEGER NOT NULL, NAME VARCHAR(200) NOT NULL ); insert into bbs (PARENTID,ID,NAME) values (0,1,'数据库开发'); insert into bbs (PARENTID,ID,NAME) values (1,11,'DB2'); insert into bbs (PARENTID,ID,NAME) values (11,111,'DB2 文章1'); insert into bbs (PARENTID,ID,NAME) values (111,1111,'DB2 文章1 的评论1'); insert into bbs (PARENTID,ID,NAME) values (111,1112,'DB2 文章1 的评论2'); insert into bbs (PARENTID,ID,NAME) values (11,112,'DB2 文章2'); insert into bbs (PARENTID,ID,NAME) values (1,12,'Oracle'); insert into bbs (PARENTID,ID,NAME) values (0,2,'Java 技术'); COMMIT;
那么,现在让你查询一下DB2 的所有文章及评论,怎么办?传统的方法就
很难查询了,这时候递归查询就派上用场了,如下:
WITH TEMP(PARENTID,ID,NAME) AS ( SELECT PARENTID,ID,NAME FROM BBS WHERE NAME='DB2'---语句1 UNION ALL---语句2 SELECT B.PARENTID,B.ID,B.NAME FROM BBS AS B, TEMP AS T WHERE B.PARENTI D=T.ID---语句3 ) SELECT NAME FROM TEMP;---语句4
运行后,我们发现,结果完全正确,那它到底是怎么运行的呢?下面我们详细讲解一下。
1、首先,语句1 将会执行,它只执行一次,作为循环的起点。得到结果集:DB2
2、接着,将循环执行语句3,这里我们有必要详细介绍一下。
首先语句3 的意图是什么呢?说白了,它就是查找语句1产生结果集(DB2)的下一级,那么在目录树中DB2 的下一级是什么呢?是‘DB2 文章1’和‘DB2 文章2’,并且把查询到的结果集作为下一次循环的起点,然后查询它们的下一级,直到没有下一级为止。
怎么样?还没明白?哈哈,不要紧,我们一步一步来:
首先,语句1 产生结果集:DB2,作为循环的起点,把它和BBS 表关联来查找它的下一级,查询后的结果为:‘DB2 文章1’和‘DB2 文章2’接着,把上次的查询结果(也就是‘DB2 文章1’和‘DB2 文章2’)和BBS 表关联来查找它
们的下一级,查询后的结果为:‘DB2 文章1 的评论1’ 和‘DB2 文章1 的评论2’。然后,在把上次的查询结果(也就是‘DB2 文章1 的评论1’ 和‘DB2 文章1 的评论2’)和BBS 表关联来查找它们的下一级,此时,没有结果返回,循环结束。
3、第三,将执行语句2,将所有的结果集放在一起,最终得到temp 结果集。
4、最后,我们通过语句4 从temp 临时集合中得到我们期望的查询结果。怎么样,这回理解了吧,如果还没有理解,那么我也无能为力了。
需要特别提醒的是
1、一定要注意语句3 的关联条件,否则很容易就写成死循环了。
2、语句2必须是UNION ALL
接下来,如果做如此更改后,再次执行WITH 递归语句
UPDATE BBS SET ID = 1 WHERE PARENTID = 1;
再次执行则会出现以下错误:
ERROR:ORA-32044:执行递归WITH查询时检测到循环
这时候,可以使用CYCLE语句忽略循环导致的错误,如下:
WITH TEMP(PARENTID,ID,NAME) AS ( SELECT PARENTID,ID,NAME FROM BBS WHERE NAME='DB2'---语句1 UNION ALL---语句2 SELECT B.PARENTID,B.ID,B.NAME FROM BBS AS B, TEMP AS T WHERE B.PARENTI D=T.ID---语句3 ) CYCLE ID SET DUP_IND TO 'Y' DEFAULT 'N' SELECT NAME FROM TEMP;---语句4
此时我们得到多了一列出来,DUP_IND
(PS.需要注意的是,这个结果和使用CONNECT BY NOCYCLE得到的结果并不一致,ID为1的记录会出现两次。后面会降到CONNECT BY语句的使用)
DUP_IND为’Y’的时候,表示出现了死循环。
同时CYCLE可以判断在在同一叶子上是否出现重复的值。
如果执行:
insert into bbs (PARENTID,ID,NAME) values (11,112,'DB2 文章1');
再次执行带CYCLE的递归查询语句。
也会发现有一个’Y’在上面,因为后面的“DB2 文章1”内容重复了。
但是,如果执行的插入数据语句是:
insert into bbs (PARENTID,ID,NAME) values (111,1113,'DB2 文章1');
则不会出现Y。
发表评论
-
你真的会SQL吗?关于SQL的join和on之间的区别
2014-12-05 22:11 2634写了那么多年的SQL,居然发现自己写的是错的,实在是惭愧不 ... -
慎用堆表
2014-11-18 11:14 1497有时候我们常常为了使用方便,省略建主键的建表方式。 因为很 ... -
Oracle谓词推入
2014-04-08 09:20 7124在Oracle中,谓词一般就是指where后面的那些过滤条 ... -
Oracle 执行计划
2013-11-14 10:40 0explain plan for select a.produ ... -
Oracle Share Pool 与ORA-04031
2013-07-16 11:25 1826oracle share pool详解:http://blo ... -
Oracle 分析函数Lead(),Lag()
2013-04-22 21:18 12863其实这2个函数的作用非常好理解,Lead()就是取当前顺序的 ... -
总结Oracle数组和BULK COLLECT INTO
2013-04-19 23:29 1807Oracle中使用数组,就像JAVA使用对象List< ... -
[转]Oracle表连接方式学习
2013-04-10 20:40 1502出自:http://www.itpub.net/threa ... -
Oracle SQL 嵌套CASE WHEN
2013-04-09 20:11 13238尝试了一下,Oracle CASE WHEN 是可以支持嵌套 ... -
Oracle FUNCTION与PROCEDURE的最大区别
2013-04-03 15:12 1881Oracle function里面是可以允许有DML语句的, ... -
Oracle Merge into语句
2013-03-29 15:35 2889研究这个语句完全是为了偷懒而使用的。 因为在Java写后 ... -
Oracle填坑指南之长度为0的字符串
2013-03-18 16:20 1412用一下语句查询,你认为结果是什么?? select cas ... -
Oracle数据库设计中的不更新原则
2013-02-04 16:39 1157在新增数据的时候,如果新的逻辑涉及到原有的信息,那么尽量是能 ... -
Oracle SQL判断字符串是否在目标字符串中的函数
2013-01-18 15:33 5648根据需求,写了一段方法。 用于识别以下的情况: 判断 字 ... -
[转]Oracle中使用正则表达式
2012-11-13 14:05 1444Oracle10开始支持正则表达式。 介绍内容如下: OR ... -
Oracle中使用Java存储过程
2012-11-13 13:51 1619从Oracle8i开始,就有了对Java存储过程的支持。 O ... -
Oracle索引的新认识
2012-11-08 16:16 1329首先,Oracle的索引有。 普通索引B*树,BitMap索 ... -
Oracle和Cognos Framework Manager中decode妙用,CASE WHEN也可以!
2012-11-05 17:44 2807我们都知道Decode函数可以用来做什么作用,如果这个不知道的 ... -
Oracle 数组类型
2012-10-16 11:07 4898Oracle的数组类型,范例 ... -
Oracle 列转行函数 Listagg()
2012-10-16 09:58 175032这是一个Oracle的列转行函数:LISTAGG() ...
相关推荐
Oracle 常用 SQL 语句汇总 Oracle 是一个功能强大且复杂的关系数据库管理系统,它提供了多种 SQL 语句来管理和操作数据库。在本文中,我们将详细介绍 Oracle 中常用的 SQL 语句,包括数据控制语句(DML)、数据定义...
### Oracle基本建表语句知识点总结 #### 一、创建用户 在Oracle数据库中,创建用户是基础操作之一。这通常用于控制不同开发者或应用程序之间的访问权限。 **语法:** ```sql CREATE USER <username> IDENTIFIED BY...
通过本文,我们详细介绍了Oracle数据库中 `START WITH` 和 `CONNECT BY` 的使用方法以及应用场景。这两个关键字对于处理具有层级结构的数据非常有用。此外,我们还讨论了如何利用 `LEVEL` 关键字来显示节点所在的...
### Oracle万能查询语句详解 #### 一、概述 在Oracle数据库中,查询语句是数据检索的核心工具。本文将详细介绍一个复杂的Oracle查询语句,该语句涉及多个表的连接、序列、存储过程以及多表查询等相关知识点。通过...
在Oracle中,创建自增序列可以使用`CREATE SEQUENCE`语句,如创建一个名为`class_seq`的序列: ```sql CREATE SEQUENCE class_seq INCREMENT BY 1 START WITH 1 MAXVALUE 999999 NOCYCLE NOCACHE; ``` 然后,在插入...
本篇将深入探讨Oracle关于日期的查询语句及其相关知识点。 1. 数据类型: Oracle提供了多种日期和时间数据类型,包括DATE、TIMESTAMP、TIMESTAMP WITH TIME ZONE以及TIMESTAMP WITH LOCAL TIME ZONE。其中,DATE...
9. **分页**:`LIMIT`和`OFFSET`在某些数据库系统中用于实现数据分页,但Oracle使用`ROWNUM`或`FETCH NEXT`结合`WITH TIES`来实现类似功能。 10. **动态SQL**:允许在运行时构建和执行SQL语句,增强了SQL的灵活性,...
根据提供的文件信息,我们可以深入探讨Oracle数据库中的...通过以上的详细介绍,我们已经了解了在Oracle数据库中如何创建序列、使用各种约束以及如何解锁用户的基本方法。这些技能对于维护和管理Oracle数据库至关重要。
对于需重复查询的sql语句,可巧用with as 对sql语句进行精简,提高查询效率
在提供的示例中,使用了`JOIN...USING`语法的变体,即`JOIN...WITH (+)`(在Oracle中,这是一种过时的表示法,现代语法更倾向于使用`LEFT JOIN`): ```sql SELECT a.*, b.skill FROM students a, student_skill b...
我们都知道在9i之前,要想获得建表和索引的语句是一件很麻烦的事。我们可以通过 export with rows=no来得到,但它的输出因为格式的问题并不能...使用这个功能强大的工具,我们可以获得单个对象或整个SCHEMA 的DDL语句。
* 用 Transact-SQL 语句创建索引:使用 CREATE INDEX 语句创建索引,例如 CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name ON { table | view } ( column [ ASC | DESC ] [ ...n ] ) [ WITH [PAD_...
### Oracle基本建表语句集知识点详解 #### 创建用户 - **语法**: ```sql CREATE USER <用户名> IDENTIFIED BY <密码> DEFAULT TABLESPACE <表空间名> TEMPORARY TABLESPACE <临时表空间名>; GRANT <角色>,<角色...
### Oracle常用SQL语句详解 #### 数据控制语句(DML) **1. INSERT语句** 插入数据到表中的操作通过`INSERT`语句实现。基本语法如下: ``` INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...)...
本文将详细解析Oracle的基本建表语句以及相关的数据库操作。 首先,创建用户是数据库管理的第一步。以下是一个创建用户`han`的示例: ```sql CREATE USER han IDENTIFIED BY han DEFAULT TABLESPACE users ...
- `SELECT`语句基本兼容,但Oracle的`WITH`子句在DB2中可能需要额外的语法调整。 - Oracle的`ROWNUM`用于行号,DB2则使用`ROW_NUMBER()`函数。 - 分区查询,Oracle的`PARTITION BY`在DB2中对应`WINDOW`函数。 4....
### 使用简单的SQL语句实现的Oracle数据库分页技术 #### 环境:Oracle 9i 在Oracle数据库中实现分页查询是一项常见的需求,尤其是在处理大量数据时。本文将介绍一种利用简单SQL语句来实现Oracle数据库分页的方法,...
接下来将详细介绍一些常用的Oracle系统表语句及其应用场景。 首先,对于统计分析,`ANALYZE TABLE`语句用于收集表或索引的统计信息,这有助于优化器更好地制定执行计划,从而提升查询效率。例如: ```sql ANALYZE ...