With语句的语法(AS后面的括号是不可以空缺的)
1WITH<alias_name>AS (subquery_sql_statement)
2SELECT<column_name_list>FROM<alias>;
简单的with语句:
WITH A AS
(SELECT*FROM DUAL)
SELECT*FROM A
注意,定义了WITH语句必须在后边的查询中使用,否则提示错误信息:
1WITH A AS
2 (SELECT*FROM DUAL)
3SELECT*FROM dual
(错误的原因是因为没有使用定义的WITH语句进行查询)
两个with语句的语法:
1WITH<alias_one>AS
2 (subquery_sql_statement),
3<alias_two>AS
4 (sql_statement_from_alias_one)
5SELECT<column_name_list>
6FROM<alias_one>, <alias_two>
7WHERE<join_condition>;
测试例子:
1WITH A AS
2 (SELECT*FROM DUAL),
3 B AS
4 (SELECT*FROM DUAL)
5SELECT*FROM B, A
当在FROM关键子后面没有全部使用定义的WITH语句,他就会提示同上的错误信息:
(不可引用在with子句中定于的查询)
在视图中使用WITH语句进行连接:
1CREATEORREPLACEVIEW WITH_V AS
2WITH DEPT_V AS (SELECT*FROM DEPT),
3 EMP_V AS (SELECT*FROM EMP)
4SELECT D.DNAME,D.LOC,E.*FROM EMP_V E
5LEFTJOIN DEPT_V D
6ON D.DEPTNO = E.DEPTNO
使用WITH AS 语句可以为一个子查询语句块定义一个名称,使用这个子查询名称可以在查询语句的很多地方引用这个子查询。Oracle 数据库像对待内联视图或临时表一样对待被引用的子查询名称,从而起到一定的优化作用。with子句是9i新增语法。你可以在任何一个顶层的SELECT 语句以及几乎所有类型的子查询语句前,使用子查询定义子句。被定义的子查询名称可以在主查询语句以及所有的子查询语句中引用,但未定义前不能引用。with子句中不能嵌套定义<也就是with子句中不能有with子句>,但子查询中出现的“子查询定义”语句可以引用已定义的子查询名称。<可以引用前面已经定义的with子句>
WITH子句相关总结:
1、在同级select前有多个查询定义的时候,第1个用with,后面的不用with,并且用逗号隔开。
2、最后一个with 子句与下面的查询之间不能有逗号,只通过右括号分割,with 子句的查询必须用括号括起来
3、如果定义了with子句,而在查询中不使用,那么会报ora-32035 错误:未引用在with子句中定义的查询名。(至少一个with查询的name未被引用,解决方法是移除未被引用的with查询),注意:只要后面有引用的就可以,不一定非要在主查询中引用,比如后面的with查询也引用了,也是可以的。
4、前面的with子句定义的查询在后面的with子句中可以使用。但是一个with子句内部不能嵌套with子句。
5、with查询的结果列有别名,引用的时候必须使用别名或*。
WITH语句的优点:
(1). SQL可读性增强。比如对于特定with子查询取个有意义的名字等。
(2)、with子查询只执行一次,将结果存储在用户临时表空间中,可以引用多次,增强性能。
举例:在进行导入EXCEL的过程中,有时候,需要将数据存储在临时表中,当下一次在进行导入的时候,进行清除临时表的数据,但是这时候,有时候发生并发问题的话,两个用户可能会分别操作对方的数据,所以,可能造成混乱,但是可以使用WITH函数和UNION语句拼接一个SQL语句,存储在SESSION中,当需要导出错误信息的时候,可以使用该语句构造数据。
---------------------------WITH语句的使用例子:
1、查询出部门的总薪水大于所有部门平均总薪水的部门。部门表s_dept,员工表s_emp。分析:做这个查询,首先必须计算出所有部门的总薪水,然后计算出总薪水的平均薪水,再筛选出部门的总薪水大于所有部门总薪水平均薪水的部门。那么第1 步with 查询查出所有部门的总薪水,第2 步用with 从第1 步获得的结果表中查询出平均薪水,最后利用这两次的with 查询比较总薪水大于平均薪水的结果,如下:
1WITH DEPT_COSTS AS--查询出部门的总工资
2 (SELECT D.DNAME, SUM(E.SAL) DEPT_TOTAL
3FROMDEPT D, EMP E
4WHERE E.DEPTNO =D.DEPTNO
5GROUPBYD.DNAME),
6 AVE_COST AS--查询出部门的平均工资,在后一个WITH语句中可以引用前一个定义的WITH语句
7 (SELECTSUM(DEPT_TOTAL) /COUNT(*) AVG_SUM FROMDEPT_COSTS)
8SELECT * from AVE_COST