子查詢:

用子查詢能解決的問題

假想你想要寫一個查詢來找出掙錢比陸濤的薪水還多的人。為了解決這個問題,你需要兩個查詢:一

 

個找出陸濤的收入,第二個查詢找出收入高于陸濤的人。

你可以用組合兩個查詢的方法解決這個問題,放置一個查詢到另一個查詢中。

內查詢或子查詢返回一個值給外查詢或主查詢。使用一個子查詢相當于執行兩個連續查詢并且用第一個

 

查詢的結果作為第二個查詢的搜索值。

 

子查詢語法:

SELECT select_list

FROM table

WHERE expr operator

              (SELECT select_list

              FROM table);

1.子查詢(內查詢) 在主查詢之前執行一次

2.子查詢的結果被用于主查詢(外查詢)

首先執行子查詢 (內查詢) 顯示子查詢返回的值,然后用內查詢返回的結果執行外查詢,最后,執行整個查詢 (包括子查詢),顯示相同的結果。

 

 

子查詢可嵌套的位置:

子查詢是一個SELECT 語句,它是嵌在

另一個 SELECT 語句中的子句。

使用子查詢你可以用簡單的語句構建功能強大的語句。當你需要從表中用依賴于表本身的數據選擇行時

 

它們是非常有用的。

也可以放在

WHERE 子句 HAVING 子句 FROM 子句。

 

在語法中:

operator 包括比較條件,例如 >= IN

比較條件分為兩個種類:單行運算符 (>, =, >=, <, <>, <=) 和多行運算符 (IN, ANY, ALL)

子查詢通常涉及一個嵌套的 SELECT、子-SELECT 或內 SELECT 語句。字查詢通常執行一次。并且它的輸出被用于完成主或外查詢的查詢條件。

 

另外,子查詢可以被放在 CREATE VIEW 語句中、CREATE TABLE 語句、UPDATE 語句、INSERT 語句的 INTO 子句和 UPDATE 語句的 SET 子句中。

 

使用子查詢的原則:

1.       子查詢放在圓括號中

2.將子查詢放在比較條件的右邊, 以增加可讀性。

在子查詢中的ORDER BY 子句不需要,除非你正在執行Top-N 分析。

Oracle8i 以前的版本中,子查詢不包含 ORDER BY 子句。對一個 SELECT 語句只能用一個 ORDER BY 子句,并且如果指定了它就必須放在主 SELECT 語句的最后。從 Oracle8i 開始,ORDER BY 子句可以使用,并且在進行 Top-N 分析時是必須的。

3.在單行子查詢中用單行運算符,在多行子查詢中用多行運算符,

在子查詢中可以使用兩種比較條件:單行運算符和多行運算符。

子查詢的個數:

Oracle 服務器沒有強制限制子查詢的數目;限制只與查詢所需的緩沖區大小有關。

 

子查詢的類型:

1.    單行子查詢:從內 SELECT 語句只返回一行的查詢

2.       多行子查詢:從內 SELECT 語句返回多行的查詢

3.    還有多列子查詢:從內 SELECT 語句返回多列的查詢。

 

單行子查詢

單行子查詢是從內查詢返回一行的查詢。在該子查詢類型中用一個單行操作符

SELECT last_name, job_id

FROM employees

WHERE job_id =

(SELECT job_id

FROM employees

WHERE employee_id = 141);

 

 

SELECT  last_name, job_id, salary

FROM employees

WHERE job_id =

(SELECT  job_id  FROM  employees  WHERE  employee_id = 141)  AND  salary >(SELECT  salary  FROM  employees  WHERE  employee_id = 143);

該例子可以由三個查詢塊組成:外查詢和兩個內查詢。內查詢塊首先被執行,產生查詢結果分別為 ST_CLERK 2600。然后處理外查詢塊,并且使用內查詢的返回值來完成它的查詢條件。

兩個內查詢返回單個值 (分別是 ST_CLERK 2600),所以這種 SQL 語句被稱為單行子查詢。

注:外和內查詢可以從不同的表中取得數據。

 

在子查詢中使用組函數:

SELECT  last_name,  job_id,  salary

FROM  employees

WHERE  salary =

(SELECT  MIN(salary) FROM  employees);

你可以從主查詢中顯示數據,該主查詢使用一個帶組函數的單行子查詢。子查詢放在圓括號中并且放在比較條件的后面。

例子顯示所有其薪水等于最低薪水的雇員的 last namejob ID salary MIN 組函數返回單個的值 (2500) 給外函數。

 

帶子查詢的HAVING 子句:

1.Oracle 服務器首先執行子查詢

2.Oracle 服務器返回結果到主查詢的HAVING 子句中

找出平均薪水為最低平均薪水的工作崗位。

SELECT job_id, AVG(salary)

FROM employees

GROUP BY job_id

HAVING AVG(salary) = (SELECT MIN(AVG(salary))

FROM employees

GROUP BY job_id);

 

子查詢錯誤

使用子查詢的一個常見的錯誤是單行子查詢返回返回了多行。

SELECT employee_id, last_name

FROM employees

WHERE salary =

(SELECT MIN(salary) FROM employees  GROUP  BY  department_id);

ERROR at line 4:ORA-01427: single-rowsubqueryreturns more thanone rowERROR

子查詢包含一個 GROUP BY 子句,這就暗示該子查詢將返回多行,每個對應它所找到的一組,在這種情況下,子查詢的結果將是 4400600025004200700017000 8300

外查詢得到子查詢的結果 (44006000250042007000170008300) 并且在它的 WHERE 子句中使用這些結果。WHERE 子句包含一個等號 (=) 運算符,這是一個單行比較運算符,只能使用一個值。 = 操作符不能接受來自子查詢的多個值,并且因此產生錯誤。

為了糾正該錯誤,改變 = 操作為 IN

子查詢的另一個常見問題是內查詢沒有返回行。

,子查詢包含一個 WHERE 子句,推測起來,其目的是找名字為 Haas 的雇員,該語句是正確的,但在執行時選擇無行返回。

沒有名叫 Haas 的雇員,所以子查詢無返回行,外查詢得到子查詢的結果 (null) 并且在 WHERE 子句中使用該結果,外查詢找不到一個 job ID 等于 null 的雇員,所以也沒有行返回。如果一個 job 存在 null 值,也沒有返回行,因為比較兩個空值還是空,因此 WHERE 子句的條件不為 true

多行子查詢:

多行子查詢

子查詢返回多行被稱為多行子查詢。對多行子查詢要使用多行運算符而不是單行運算符。多行運算符期待多個值。

查找各部門收入為部門最低的那些雇員。

SELECT last_name, salary, department_id

FROM employees

WHERE salary IN (SELECT MIN(salary)

FROM employees

GROUP BY department_id);

內查詢先被執行,產生一個查詢結果,然后主查詢塊處理和使用由內查詢返回的值完成它的搜索條件。事實上,在 Oracle 服務器看起來主查詢象是下面這樣:

SELECT last_name, salary, department_id

FROM employees

WHERE salary IN (2500, 4200, 4400, 6000, 7000, 8300, 8600, 17000);

在多行子查詢中使用ANY 運算符

SELECT employee_id, last_name, job_id, salary

FROM employees

WHERE salary < ANY(SELECT salaryFROM employeesWHERE job_id = 'IT_PROG')

AND  job_id <> 'IT_PROG';

ANY 運算符 (和它的同義詞, SOME 運算符) 比較一個值與一個子查詢返回的每一個值。幻燈片中的例子顯示不是 IT 程序員的雇員,并且這些雇員的的薪水少于IT 程序員。掙錢最多的程序員的薪水是 $9,000

<ANY