SQL新手教程

来自KlniuWiki
跳转到: 导航, 搜索

SQL是結構化查詢語言(Structured Query Language)的縮寫。這種語言允許我們對數據庫進行複雜的查詢。同時也提供了創建數據庫的方法。SQL語言的使用範圍非常廣泛。許多數據庫產品都支持SQL語言,這意味着如果我們學會了SQL語言,我們可以把這種知識運用到MS Access 或 SQL Server, Oracle, DB2以及非常多的其它數據庫中。

SQL語言運用在關係型數據庫中。一個關係型數據庫把數據存儲在表(也稱關係)中。每個數據庫的主要組成就是一組表。每個表又由一組記錄組成--每條記錄在表中有相同的結構,包含固定數量的具有一定類型的字段。

目錄

1 術語

數據庫(Database)
存儲有一定組織數據的一個容器(通常是一個或者一組文件)。
表(Table)
存儲特殊數據類型的一個結構化列表。
表名(Table Names)
數據庫中的每一個表都有一個唯一的名字用於標識。
視圖(Schema)
關於數據庫的信息以及表的布局與性質。
列(Column)
所有的表是由一列或者多列組成的,例如將表劃分為網格的形式,在網格中的每一列都包含一段特殊的信息。
數據類型(DataType)
被允許輸入的數據類型,表格中的每一列都被限制只能輸入特殊的數據類型,比如整型、字符串、文本等。
行(Rows)
表中的一條記錄視作一行,例如將表劃分為網格的形式,在網格中的每一行都包含一系列的信息,比如一個人的姓名、年齡、職業等等可以視作一條記錄或者一行,多行則表示多個人的記錄。
主鍵(Primary Keys)
表中的一列或者幾列,其中的值可以輸入唯一的值,用以和其他行區別,這個主鍵可以用來標識行的不同,比如ID,編號等等。
子句(Clause)
SQL語句是由子句組成的,有些是必須的,有些是可選的,一個子句一般是由關鍵字和需要進行操作的數據組成的。
空值(NULL)
表示沒有值,即不等於0,也不是空字符串或者空格。

2 Note

  • 本文使用的例子大部分來源於 Sams Teach Yourself SQL in 10 Minutes, Third Edition,可以查看參見,例表可以從 http://www.forta.com/books/0672325675/ 下載,並執行其中的語句。
  • SQL會忽略空白字符,因此,你可以在編寫語句的時候換行,以方便閱讀與調試。
  • 當存在多條SQl語句時,必須在每條語句後添加一個分號(;),一些客戶端在執行單個SQL語句的時候也需要在語句結尾添加分號(;),當然,有些並不需要,如果你不管客戶端是否要求,均在SQL語句後面添加(;)是沒有錯的。
  • SQL的關鍵字是不區分大小寫的,例如,SELECT和select是一樣的,當然,大家都習慣使用大寫來表示SQL關鍵字,便於閱讀與調試,但切記,數據庫內容,比如表名,字段都是區分大小寫的。

3 查詢數據

3.1 查詢單列數據

SELECT prod_name
FROM Products;

上面的語句表示從表 Products 中查詢列名為 prod_name 的所有記錄。SELECT 後跟要查詢的列名,FROM 後跟表的名稱,表示要在哪個表進行查詢。

3.2 查詢多列數據

SELECT prod_id, prod_name, prod_price
FROM Products;

上面的語句表示從表 Products 中查詢列名分別為 prod_id、prod_name、prod_price 的數據,和單列數據不同的是,在查詢多列時,列名之間要用逗號(,)分開。

3.3 查詢所有列數據

SELECT *
FROM Products;

上面的語句表示從表 products 中查詢所有列的記錄。*為通配符,表示全部列。

Note: 在實際使用的過程中,如果不要需要查詢所有表的情況下,不建議使用通配符,因為它為增加查詢的時間,當然,如果你在不知道列名的情況下,也是可以使用*通配符來查詢的。

4 數據排序

4.1 數據排序

SELECT prod_name
FROM Products;

上面的數據在返回結果時並不是排過序的,它經常會出現不同的順序。如果要對 SELECT 查詢的數據進行排序,則需要使用 ORDER BY 子句,並依據一列或者多列進行排序。例如:

SELECT prod_name
FROM Products
ORDER BY prod_name;

上句表示從 Products 中查詢 prod_name 列,並依據 prod_name 進行排序,當使用 ORDER BY 子句進行排序時,此子句要放在 SELECT 語句的最後,

4.2 多列數據排序

有時候需要對多列數據進行排序,例如:

SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price, prod_name;

上面的語句表示從表 Products 中查詢列名 prod_id、prod_price、prod_name 的數據,並優先按照 prod_price 排序,重複項再按照 prod_name 排序。

4.3 從列的索引位置對數據排序

排序除了使用列的名字外,還可以使用列在表中的相對位置進行排序,例如:

SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY 2, 3;

上面排序是按照第2與第3的列表進行排序的。而prod_price和prod_name就正好是表中的第2列與第3列。

4.4 指定排序方向

默認的排序都是按照升序排列的,比如從A-Z,不過可以指定 DESC 關鍵字降序排列。例如:

SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price DESC;

DESC 關鍵字指定的列進行降序排列,如果進行多列排序的時,可以為每列指定排序的方式,例如:

SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price DESC, prod_id, prod_name DESC;

上面語句prod_price、prod_name 列進行降序排序,prod_id 按照默認的升序排序。

5 篩選數據

5.1 篩選數據(初步)

數據庫通常都包含大量的數據,用戶很少會需要全部的數據的,因此就要對數據進行篩選,下面將介紹 SELECT 語句 WHERE 子句的篩選功能。

在 SELECT 語句中,可以通過 WHERE 子句對數據進行篩選,WHERE 子句一般放在 FROM 關鍵字的右邊。例如:

SELECT prod_name, prod_price
FROM Products
WHERE prod_price = 3.49;

上面表示顯示錶 Products 中 prod_price 列數值為 3.49 的記錄,且只顯示 prod_name 和 prod_price 列。

Note: 在 Picky PostgreSQL 數據庫程序中,PostgreSQL 對傳入的數據要求非常嚴格,因此上例需要將 = 3.49 替換為 = decimal '3.49'。

WHERE 子句不僅可以進行是否相等的比較,還有以下比較的方式,下表列出的一些操作符有重複的,而且不是所有的數據庫管理系統對這些都支持,具體請參看系統的手冊:

Operator Description
= 相等
<> 不等
!= 不等
< 小於
<= 小於等於
!< 不小於
> 大於
>= 大於等於
!> 不大於
BETWEEN 在兩值之間
IS NULL 空值

下面再給出幾個例子:

查詢所有小於10的記錄

SELECT prod_name, prod_price
FROM Products
WHERE prod_price < 10;

查詢不符合的記錄

SELECT vend_id, prod_name
FROM Products
WHERE vend_id <> 'DLL01';

對於非數字類型,比如文本,字符串,需要使用單引號,但數值類型的值就不能使用單引號了。

查詢一個範圍的數據

SELECT prod_name, prod_price
FROM Products
WHERE prod_price BETWEEN 5 AND 10;

BETWEEN 關鍵字後面必須跟兩個數值,表示一個範圍,且兩數值中間以一個 AND 連接,且此範圍包括指定的這兩個數值。

查詢為空值的記錄

SELECT prod_name
FROM Products
WHERE prod_price IS NULL;

5.2 篩選數據(高級)

上述的篩選數據功能一次只使用一個條件進行篩選,如果要使用多級篩選功能,就要使用 AND 和 OR 操作符將條件進行連接,執行多級篩選。

5.2.1 使用 AND 操作符

AND 表示與功能,意味着篩選出的數據必須滿足所有的條件。

SELECT prod_id, prod_price, prod_name
FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4;

上面表示篩選出的數據必須同時滿足 vend_id 為 DLL01 和 prod_price 小於等於 4 兩個條件。

5.2.2 使用 OR 操作符

OR 表示或功能,意味着數據只需要滿足OR連接的條件中的一個或者多個即可。

SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01';

上面表示篩選出的數據只要滿足 vend_id 為 DLL01 和 prod_price 小於等於 4 中的一個或兩個條件即可。

5.2.3 表達式的順序

WHERE 子句後面可以跟任意多個的 AND 和 OR 操作符,連接這些操作符就可以執行高級和複雜的篩選功能。

SELECT prod_name, prod_price
FROM Products
WHERE (vend_id = 'DLL01' OR vend_id = 'BRS01')
    AND prod_price >= 10;

上句表示篩選出,vend_id 為 DLL01 或者 BRS01,並且 prod_price 小於等於 10 的數據,但如果將上句的括號去掉,出現的結果就會出現問題,因為 AND 的優先級比 OR 高,所以 vend_id = 'BRS01 就會和 prod_price >= 10 先結合,之後再和 vend_id = 'DLL01' 結合。

Tip: 建議在使用多個條件時,將表達式用括號括起來,這樣便於閱讀,且不容易出錯

5.2.4 使用 IN 操作符

IN 操作符用來指定一系列條件的範圍,其中的任一條件都可以被匹配,IN 後跟一個用括號包起來的一系列值,並用逗號(,)分隔。

SELECT prod_name, prod_price
FROM Products
WHERE vend_id  IN ('DLL01','BRS01')
ORDER BY prod_name;

上句表示將篩選出所有 vend_id 為 'DLL01' 或 'BRS01' 的數據,並按照 prod_name 進行排序。

IN 操作符的作用就類似於 OR,不過它還有以下優點:

  • 當使用一個多條件的列表時,IN 更加簡單,易於閱讀。
  • 使用IN操作符,不用擔心操作符的優先級問題。
  • IN 的執行速度比 OR 快。
  • 最大的好處是,IN 後跟的條件列表中可以使用 SELECT 語句。

5.2.5 使用 NOT操作符

NOT 操作符的作用是對條件取反,且不能單獨使用,只能後跟條件。

SELECT prod_name
FROM Products
WHERE NOT vend_id  = 'DLL01'
ORDER BY prod_name;

上句將取 vend_id 不為 'DLL01'的數據。也就是說 NOT vend_id = 'DLL01' 也可表示為 vend_id <> 'DLL01'。

Note: 在MySQL中,NOT 操作符只能和 EXIST 連接,表示是否存在,不能表示像上述一樣應用。

6 使用通配符

通配符的作用是能夠代替那些不知道或者數量比較大的列或者字段。當要使用通配符是,需要在包含通配符的字符串的前面加上 LIKE 斷言,以告訴數據庫系統後面需要匹配的是一個包含通配符的字符串。

Note: 通配符只能應用於字符串與文本,不能用於非字符串型數據類型。

通配符很強大,但需要注意以下幾點:

  • 不要過度使用通配符,如果有一個檢索操作能夠代替通配符的話,就盡量使用沒有通配符的操作。
  • 當使用通配符時,除非非常需要,不要在檢索模式的開始就使用它,因為通配符檢索會減緩操作的速度。
  • 注意使用通配符來替換字符,如果替換的位置錯誤,將得不到正確的結果。

6.1 百分號(%)通配符

百分號(%)可以匹配任意數量的任意字符,包括0個。例如,下面語句將匹配 prod_name 中所有以'Fish'開頭的字符串。

SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE 'Fish%';
Note: 如果你使用 Microsoft Access,你可能需要使用星號(*)來代替百分號(%)。

百分號(%)可以使用多個以及多個位置,比如 '%Fish%'、'F%sh'、'F%s%'。

Note: 在許多DBMS中,包括 Microsoft Access,假如一個字段是默認設定寬度為31字符,而實際字符只有17個字符,那麼,系統就會在字符串尾加上空格以補全31個字符,於是,在使用通配符的時候,F%sh並不能匹配正確,為此,解決辦法之一是使用F%sh%,另一種辦法是使用函數功能來修整空格。

6.2 下劃線(_)通配符

下劃線(_)匹配任意的單個字符。

Note: 如果你使用 Microsoft Access,你可能需要使用問號(?)來代替下劃線(_)。
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE '% inch teddy bear';

6.3 中括號([])通配符

中括號([])用來匹配一組字符中的一個。例如,以下語句匹配 cust_contact 列中,以 J 或 M 開頭的字符串。

SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '[JM]%'
ORDER BY cust_contact;
Note: 不是所有的 DBMS 均支持中括號通配符,支持中括號的有 Microsoft Access、Microsoft SQL Server、Sybase Adaptive Server。

中括號([])通配符還可以使用^來取反,比如[^JM]是匹配不為J或M的任意單個字符。

Note: 如果你使用 Microsoft Access,你可能需要使用 ! 來代替 ^。

當然,仍然可以使用NOT操作符來執行相反操作,不過^更加簡潔,例如:

SELECT cust_contact
FROM Customers
WHERE NOT cust_contact LIKE '[JM]%'
ORDER BY cust_contact;

7 數據處理

當需要對數據庫內的數據進行處理或者計算然後再返回數據,就要使用區域計算。

7.1 連接兩列數據

連接數據可以使用+或者||操作符,Access、SQL Server和 Sybase support支持+操作符,DB2、Oracle、PostgreSQL 和 Sybase support 支持 ||。不過 || 開始被越來越多DBMS支持了。

例如,下面語句在返回的結果中,將 vend_country 用括號包起來,並和 vend_name 連接。

下面例子被大多數 DBMS 支持:

SELECT vend_name + ' (' + vend_country + ')'
FROM Vendors
ORDER BY vend_name;

下面的例子使用 ||:

SELECT vend_name || ' (' || vend_country || ')'
FROM Vendors
ORDER BY vend_name;

返回結果:

----------------------------------------------------
Bear Emporium                     (USA             )

Bears R Us                        (USA             )

Doll House Inc.                   (USA             )

Fun and Games                     (England         )

Furball Inc.                      (USA             )

Jouets et ours                    (France          )

在MySQL中,+和||都不被支持,如果要在MySQL中使用連接功能,需要使用函數CONCAT(),此函數將一系列的參數連接起來,例如:

SELECT CONCAT(vend_name, ' (', vend_country, ')')
FROM Vendors
ORDER BY vend_name;

上述的返回結果右邊出現一大片的空格,這是因為許多數據庫都會為長度不滿足默認長度的數值在結尾填充空格,處理空格需要使用 RTRIM()函數,該函數去除返回結果中右邊的所有空格,例如:

SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')'
FROM Vendors
ORDER BY vend_name;

返回:

----------------------------------------------------

Bear Emporium (USA)

Bears R Us (USA)

Doll House Inc. (USA)

Fun and Games (England)

Furball Inc. (USA)

Jouets et ours (France)

The following is the same statement, but using the || syntax:

與 RTRIM() 類似,LTRIM() 去除左邊的空格,TRIM() 去除兩邊的空格。

7.2 使用別名

上述處理過的結果,並沒有列名,因此它只能用於顯示,卻不能被引用,如果客戶端想要引用的話,就必須給結果列進行命名,這就是別名的作用,可以給返回的結果列添加一個名稱,用於引用,別名需要在 AS 關鍵字之後指定,例如:

SELECT vend_name + ' (' + vend_country + ')' AS vend_title
FROM Vendors
ORDER BY vend_name;

下面的例子使用 ||:

SELECT vend_name || ' (' || vend_country || ')' AS vend_title
FROM Vendors
ORDER BY vend_name;

返回:

vend_title

----------------------------------------------------

Bear Emporium (USA)

Bears R Us (USA)

Doll House Inc. (USA)

Fun and Games (England)

Furball Inc. (USA)

Jouets et ours (France)

7.3 數學計算

下面例子將 quantity 和 item_price 相乘的結果添加別名 expanded_price 後返回:

SELECT prod_id,
       quantity,
       item_price,
       quantity*item_price AS expanded_price
FROM OrderItems
WHERE order_num = 20008;

SQL支持基本的數學運算,如加(+)、減(-)、乘(*)、除(/)。

8 使用函數

SQL中函數的作用是使數據轉換和操作更加容易,前面講到的 RTRIM() 就是一個函數。

Warning: 需要注意的是,只有很少的函數是所有的 DBMS 均支持的,DBMS 都有自己的一套函數,因此,在寫SQL的時候,你要考慮是否使用函數,並且做好注釋,以防止更換系統時麻煩。

大部分 DBMS 都只支持以下類型的函數:

  • 文本函數,習慣被用來操作文本或字符串,例如剪切或者填充,更改大小寫等。
  • 數值函數,習慣被用來操作數值,例如返回絕對值、代數運算。
  • 日期與時間函數,習慣被用來操作日期與時間值,以及從特殊的組成中提取出日期與時間,例如,返回兩個日期的差、檢查日期的有效性。
  • 系統函數,返回當前DBMS的信息,比如用戶的登陸信息等。

8.1 文本函數

下面的 UPPER() 函數的功能是轉換結果為大寫。

SELECT vend_name, UPPER(vend_name)
AS vend_name_upcase
FROM Vendors
ORDER BY vend_name;

下表列出經常使用的文本處理函數:

經常使用的文件處理函數
函數 函數描述
LEFT() (或者使用 substring 函數) 從左邊開始返回字符
LENGTH() (也可以使用 DATALENGTH() or LEN()) 返回字符串的長度
LOWER() 將字符串的大寫字符轉換為小寫
LTRIM() (在 Access 中為LCASE()) 刪除左邊空白字符
RIGHT() (或者使用 substring 函數) 從右邊開始返回字符
RTRIM() 刪除右邊空白字符
SOUNDEX() 返回一個字符串的語音表示形式。
UPPER() (在 Access 中為 UCASE()) 將字符串中的小寫字符轉換為大寫

8.2 日期和時間函數

日期和時間在表中以數據類型的形式存儲,而且每個 DBMS 都使用它們自己特殊的形式,它們存儲的形式比較特殊,以方便排序、查找和存儲。

時間和日期函數在不同的平台下,差別比較大,請查看具體手冊。

8.3 數學函數

數學函數大部分是對數值進行代數、三角、幾何計算的,很多平台的數值函數都是相同的,下面列出一些常用的數學函數。

常用的數值函數
函數 描述
ABS() 返回數值的絕對值
COS() 返回餘弦值
EXP() 返回針對一個特定數字的指數值
PI() 返回圓周率的值
SIN() 返回正弦值
SQRT() 返回數值的平方根
TAN() 返回數值的正弦值

8.4 統計函數

在 SQL 中,統計函數的功能是對特定列計數、計和、最值等統計作用。下表列出各類統計函數:

SQL 統計函數
函數 描述
AVG() 返回一列的平均值
COUNT() 返回行數
MAX() 返回一列中的最大值
MIN() 返回一列中的最小值
SUM() 返回一列數據的總和

所有的統計類函數都可以應該於多列。


8.4.1 AVG()平均值

AVG()平均值函數用來返回特定一列的特定行的數值的平均值。例如,下例返回 prod_price 列全部行的平均值。:

SELECT AVG(prod_price) AS avg_price
FROM Products;

當然,可以在後面加入條件限制,以針對特定行執行平均值操作。

8.4.2 COUNT()計數

計數函數是統計行數的工具,它有兩個實現的方式:

  • COUNT(*),將對所有行進行計數,不管各列是否有值。
  • COUNT(column),將對特定列內有值的行進行計數,忽略空值的行。

8.4.3 MAX()最大值

MAX()返回特定列的最大值,該函數需要一個特定列作為參數,但盡量不要將該函數應用於非數值列。例如,下例返回 prod_price 列的最大值:

SELECT MAX(prod_price) AS max_price
FROM Products;

8.4.4 MIN()最小值

MIN()返回特定列的最小值,用法於MAX()相同。

8.4.5 SUM()計和

SUM()函數返回特定列並符合條件的值的總和,該函數將忽略包含空值的項目。例如,下例返回滿足 order_num 等於20005的 quantity 列的所有值的總和。

SELECT SUM(quantity) AS items_ordered
FROM OrderItems
WHERE order_num = 20005;

SUM()函數還可以對計算過的數值進行計和。例如,下例將返回各行 item_price 和 quantity 相乘之後相加的和。

SELECT SUM(item_price*quantity) AS total_price
FROM OrderItems
WHERE order_num = 20005;

8.4.6 統計個別數據

統計類函數有兩種使用方式:

  • 一種是作用於全部滿足條件的值。
  • 一種是作用於非重複數據的值,也就是說該列中只有此一個值。如果要這樣統計的話,就需要使用 DISTINCT 關鍵字。
SELECT AVG(DISTINCT prod_price) AS avg_price
FROM Products
WHERE vendor_id = 'DLL01';

DISTINCT 不能應該用於COUNT(*)函數,因為 DISTINCT 要應用於列名之前。同時,DISTINCT 用在 MIN() 和 MAX() 上的,因為它沒有意義。

8.4.7 合并多個函數

上面的函數例子都是使用單個函數的,實際上,多個函數可以並用,比如:

SELECT COUNT(*) AS num_items,
       MIN(prod_price) AS price_min,
       MAX(prod_price) AS price_max,
       AVG(prod_price) AS price_avg
FROM Products;

9 分組查詢

9.1 創建分組

分組查詢的作用是將一列中相同的值分為一組,並統計各組情況,例如,下例的返回有兩列,一個是 vend_id,一個是 num_prods,此列是要被統計數量的列,GROUP BY 關鍵字將按照 vend_id 列進行分組和排序,同時 COUNT() 函數將對每一組的數值統計一次,而不是返回整個數組的統計值:

SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id;

返回:

vend_id    num_prods

---------    ---------

BRS01    3

DLL01    4

FNG01    2

在使用 GROUP BY 之前,需要注意以下規則:

  • GROUP BY 子句之後可以跟多個列,這個特性可以使你對組進行嵌套,以及控制怎麼分組。
  • 如果你嵌套使用 GROUP BY 子句,數據只會在最後一組被統計。
  • 在 GROUP BY 子句中列出的每一列都應該是可以被檢索的或者是一個有效的表達式。如果一個表達式在 SELECT 子句中使用了,那麼 GROUP BY 子句中也應該包含它。
  • 大部分的 DBMS 都不允許 GROUP BY 後跟可變長度的數據類型,比如文本。
  • 除了函數外,在 SELECT 語句中出現的列都應該出現在 GROUP BY 子句中。
  • 如果要分組的列內含有空值,那麼返回的結果中會將是空值的分為一組,並且這一組也將被統計。
  • GROUP BY 子句必須是 WHERE 子句之後,ORDER BY 子句這前。

有些 DBMS 支持分組的時候,按照列的索引來分組,比如 GROUP BY 2,1,具體使用請查看手冊。

9.2 過濾分組

WHERE 子句是對特定行進行過濾,但如果要過濾組就不能使用 WHERE 子句了,可以使用 HAVING 子句,HAVING 子句的用法和 WHERE 子句一樣,例如,下例將返回所有 Orders 大於或等於2的組。

SELECT cust_id, COUNT(*) AS orders
FROM Orders
GROUP BY cust_id
HAVING COUNT(*) >= 2;

WHERE 子句和 HAVING 子句的區別是 WHERE 子句過濾行,也就是說是在 GROUP BY 子句這前執行,而 HAVING 子句過濾組,在 GROUP BY 子句之後執行。例如,下例將首先過濾掉 prod_price 小於4的行,分組之後,再過濾掉總計小於2的組:

SELECT vend_id, COUNT(*) AS num_prods
FROM Products
WHERE prod_price >= 4
GROUP BY vend_id
HAVING COUNT(*) >= 2;

9.3 分組與排序

分組返回的結果並不總是按照我們的意願進行排序,或者有時候我們需要針對特定組進行排序,就要使用 ORDER BY 子句了,例如,下例分組完成後,再根據 COUNT(*) 和 order_num 進行先後排序:

SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3
ORDER BY items, order_num;
Note: Microsoft Access 不允許在排序的時候使用別名,解決辦法是,不使用別名,直接在 ORDER BY 後跟 COUNT(*) 函數即可。

10 子句順序

在學習了這麼多 SELECT 子句後,需要知道各個子句的順序是什麼樣的,見下表:

SELECT 子句及其順序
子句 描述 是否必須
SELECT 返回列或者表達式
FROM 獲取數據的來源表格 當從表格中獲取數據時需要
WHERE 過濾行 不是
GROUP BY 分組 按照組統計時需要
HAVING 過濾組 不是
ORDER BY 對輸出排序 不是

11 子查詢

11.1 子查詢

子查詢允許你把查詢的一個結果當作另一查詢的一部分使用,即嵌套查詢。例如,下例包含兩個子查詢,子查詢的結果將返回後作為父查詢的條件繼續參與查詢。

SELECT cust_name, cust_contact
FROM Customers
WHERE cust_id IN (SELECT cust_id
    FROM Orders
    WHERE order_num IN (SELECT order_num
        FROM OrderItems
        WHERE prod_id = 'RGAN01'));
Note: 子查詢只能獲取一列數據,獲取多列數據系統會報告錯誤。

11.2 子查詢作為計算子段

下例將對 Customers 中的每個客戶返回三列,分別為 cust_name,cust_state,orders。其中的子句在每查到一個客戶的時候都執行一次。子句中的 WHERE 關鍵字和主句中的不同,它使用了有限制的列名,因為 cust_id 在 Orders 和 Customers 中均有,且以此為聯繫進行查詢,因此需要加限定。

SELECT cust_name,
cust_state,
(SELECT COUNT(*)
        FROM Orders
        WHERE Orders.cust_id = Customers.cust_id) AS
orders
FROM Customers
ORDER BY cust_name;

12 聯結表

12.1 聯結

SQL 最強大的功能之一就是能在數據查詢的執行中聯結表。聯結是利用關係表來執行操作的,它不是物理意義上的聯結,而是查詢過程中的操作。應用聯結需要知識關係表,關係表是指兩個或者兩個以上的表中,通過一個或者多個主鍵或者唯一值進行關聯,達到互相關聯的目的,比如,可以將產品的信息和生產廠家的信息分別存儲在兩個表內,兩個表內相同的一列數據可以是生產廠商的ID,之後就可以很簡單的通過產品查詢到廠商,反之亦可。

12.2 創建聯結

創建聯結很簡單,只需要指出所有的表及其它們之間的聯繫即可。例如:

SELECT vend_name, prod_name, prod_price
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;

上例和以前的語句很相似,不同之處在於:

  • 要查詢的列 prod_name,prod_price 位於一個表內,vend_name 位於另一個表內。
  • FROM 後跟兩個表,表示從兩個表內查詢數據。
  • WHERE 子句後跟一個帶有限定範圍的表達式,出現限定符的原因是,因為有兩個表,且其字段都為 vend_id,因此,需要指明方可。
Note: 切記在聯結表的時候一定要使用 WHERE 子句並保證其正確。

12.3 內聯結

目前為止所有的聯結都是基於兩個表的等值聯結,這種聯結也叫做內聯結。另外有種語法可以查詢到相同的結果,例如:

SELECT vend_name, prod_name, prod_price
FROM Vendors INNER JOIN Products
 ON Vendors.vend_id = Products.vend_id;

上句中的 SELECT 與前面的 SELECT 相同,但 FROM 子句不同,兩個表的關係以 INNER JOIN 指定。在使用這種語法時,聯結條件用特定的ON子句而不是WHERE子句給出。傳遞給ON的實際條件與傳遞給WHERE的相同。

12.4 聯結多個表

SQL對一條SELECT語句中可以聯結的表的數目沒有限制。創建聯結的基本規則也相同,例如:

SELECT prod_name, vend_name, prod_price, quantity
FROM OrderItems, Products, Vendors
WHERE Products.vend_id = Vendors.vend_id
       AND OrderItems.prod_id = Products.prod_id
       AND order_num = 20007;

DBMS在運行時關聯指定的每個表以處理聯結,這種處理可能非常耗費資源,因此應該仔細,不要聯結不必要的表,聯結的表越多,性能下降越厲害。

12.5 創建高級聯結

12.5.1 使用表別名

前面已經介紹過列別名,可以方便在結果中引用,另外SQL也支持表別名,表別名有兩個用途,一個是簡化,另一個是方便後面引用。另外,與列別名不同的是,表別名並不返回到結果中去,只是在查詢中使用。例如:

SELECT cust_name, cust_contact
FROM Customers AS C, Orders AS O, OrderItems AS OI
WHERE C.cust_id = O.cust_id
 AND OI.order_num = O.order_num
 AND prod_id = 'RGAN01';
Note: 在Oracle中,不支持使用AS來聲明別名,請使用 Customers C 來代替 Customers AS C。

13 參見

  • 深入淺出SQL入門教程. sqlzoo.cn. 
  • Ben Forta. Sams Teach Yourself SQL in 10 Minutes, Third Edition. 2004-03-31.ISBN:0-672-32567-5.
个人工具
分类
化学
[×] 國學
学佛
[×] 数学
物理
生活
[×] 英语
读书
辞典
廣告