使用WITH AS 語句可以爲一個子查詢語句塊定義一個名稱,使用這個子查詢名稱可以在查詢語句的很多地方引用這個子查詢。Oracle 數據庫像對待內聯視圖或臨時表一樣對待被引用的子查詢名稱,從而起到一定的優化作用。with子句是9i新增語法。你可以在任何一個頂層的SELECT 語句以及幾乎所有類型的子查詢語句前,使用子查詢定義子句。被定義的子查詢名稱可以在主查詢語句以及所有的子查詢語句中引用,但未定義前不能引用。with子句中不能嵌套定義<也就是with子句中不能有with子句>,但子查詢中出現的“子查詢定義”語句可以引用已定義的子查詢名稱。<可以引用前面已經定義的with子句>
with子句優點:
1. SQL可讀性增強。比如對於特定with子查詢取個有意義的名字等。
2. with子查詢只執行一次,將結果存儲在用戶臨時表空間中,可以引用多次,增強性能。
with子句語法:
With alias_name as (select1), --as和select中的括號都不能省略
alias_name2 as (select2),--後面的沒有with,逗號分割,同一個主查詢同級別地方,with子查詢只能定義一次
…
alias_namen as (select n) –與下面的實際查詢之間沒有逗號
Select ….
with子句相關總結:
1.使用with子句可以讓子查詢重用相同的with查詢塊,通過select調用(with子句只能被select查詢塊引用),一般在with查詢用到多次情況下。在引用的select語句之前定義,同級只能定義with關鍵字只能使用一次,多個用逗號分割。
2.with子句的返回結果存到用戶的臨時表空間中,只做一次查詢,反覆使用,提高效率。
3.在同級select前有多個查詢定義的時候,第1個用with,後面的不用with,並且用逗號隔開。
5.最後一個with 子句與下面的查詢之間不能有逗號,只通過右括號分割,with 子句的查詢必須用括號括起來
6.如果定義了with子句,而在查詢中不使用,那麼會報ora-32035 錯誤:未引用在with子句中定義的查詢名。(至少一個with查詢的name未被引用,解決方法是移除未被引用的with查詢),注意:只要後面有引用的就可以,不一定非要在主查詢中引用,比如後面的with
查詢也引用了,也是可以的。
7.前面的with子句定義的查詢在後面的with子句中可以使用。但是一個with子句內部不能嵌套with子句。
8.當一個查詢塊名字和一個表名或其他的對象相同時,解析器從內向外搜索,優先使用子查詢塊名字。
9.with查詢的結果列有別名,引用的時候必須使用別名或*。
with使用例子:
1.一般使用方式
- with num as (select d.deptno from dept d where d.deptno=10)
- select e.ename,e.job,e.sal from emp e where e.deptno in (select * from num);
- ENAME JOB SAL
- ---------- --------- ---------
- MILLER CLERK 1300.00
- KING PRESIDENT 5000.00
- CLARK MANAGER 2450.00
使用with 子句,可以在複雜的查詢中預先定義好一個結果集,然後在查詢中反覆使用,不使用會報錯。而且with 子句獲得的是一個臨時表,如果在查詢中使用,必須採用select from with查詢名,比如:
- with num as (select count(*) from emp e where e.deptno=10)
- select num*10 from dual;
- --是錯誤的。必須是
- with num as (select count(*) c from emp e where e.deptno=10)
- select c*10 from num;
- C*10
- ----------
- 30
2.子查詢中可以引用前面已經定義的with子句
- select e.ename from emp e where e.deptno in
- (select d.deptno from dept d where d.deptno=10);
- with a as (select e.ename,e.deptno from emp e)
- select a.ename from a where a.deptno in(
- with b as (select d.deptno from dept d where d.deptno=10)
- select * from b
- );
- with a as (select e.ename,e.deptno from emp e),
- b as (select d.deptno from dept d where d.deptno=10)
- select a.ename from a where a.deptno in (select * from b);
- ENAME
- ----------
- MILLER
- KING
- CLARK
3.一個with查詢的實例:
查詢出部門的總薪水大於所有部門平均總薪水的部門。部門表s_dept,員工表s_emp。分析:做這個查詢,首先必須計算出所有部門的總薪水,然後計算出總薪水的平均薪水,再篩選出部門的總薪水大於所有部門總薪水平均薪水的部門。那麼第1 步with 查詢查出所有部門的總薪水,第2 步用with 從第1步獲得的結果表中查詢出平均薪水,最後利用這兩次的with 查詢比較總薪水大於平均薪水的結果,如下:
- with
- --step1:查詢出部門名和部門的總薪水
- dept_costs as(
- select a.name,sum(b.salary) dept_total
- from
- s_dept a,s_emp b
- where a.id=b.dept_id
- group by a.name
- ),
- --step2:利用上一個with查詢的結果,計算部門的平均總薪水
- avg_costs as(
- select sum(dept_total)/count(*) dept_avg
- from dept_costs
- )
- --step3:從兩個with查詢中比較並且輸出查詢結果
- select name,dept_total
- from dept_costs
- where
- dept_total>
- (
- select dept_avg
- from
- avg_costs
- )
- order by name;
從上面的查詢可以看出,前面的with 查詢的結果可以被後面的with查詢重用,並且對with 查詢的結果列支持別名的使用,在最終查詢中必須要引用所有with 查詢,否則會報錯ora-32035 錯誤。
4.一個查詢,如果查詢的結果行不滿足是10 的倍數,則補空行,直到是查詢出的行數是10 的倍數。
- with a as (select 10-mod(count(*),10) from dept d) --查詢比10的倍數差幾個空行
- select t.dname,t.loc from dept t
- union all
- select null,null from all_objects --9i只能這樣寫
- where rownum <= (select * from a);
- with a as (select 10-mod(count(*),10) from dept d) --查詢比10的倍數差幾個空行
- select t.dname,t.loc from dept t
- union all
- select null,null from dual --10g可以這樣寫
- connect by rownum <= (select * from a);