結構化查詢語言/資料查詢語言
資料查詢語言用於從資料庫中提取資料。它不修改資料庫中的任何資料。它只描述一個查詢:SELECT。
每個列都有一個型別。以下是標準的 SQL 資料型別
| 資料型別 | 說明 | 允許的值 | 示例 |
| VARCHAR(n) | 最大長度為 n 的字串 | [0-9a-zA-Z]+{n} |
"foo" |
| CHAR(n) | 固定長度為 n 的字串 | [0-9a-zA-Z]{n} |
"foo" |
| SMALLINT | 16 位有符號整數 | \-?[0-9]+ |
584 |
| INTEGER | 32 位有符號整數 | \-?[0-9]+ |
-8748 |
| FLOAT | 十進位制浮點數 | \-?[0-9]+[\.[0-9]+]? |
48.96 |
| NUMBER(n,[d]) | n 位數(如果提到,則有 d 位小數位) | \-?[0-9]+[\.[0-9]+]? |
484.65 |
| DATE | 日期(YYYY-MM-DD) | [0-9][0-9][0-9][0-9]\-[0-1][0-9]\-[0-3][0-9] |
2009-03-24 |
| TIME | 60 分鐘的時間段;一天的二十四分之一 | [0-2][0-9]\:[0-5][0-9]\:[0-5][0-9] |
11:24:56 |
| TIMESTAMP | 日期和時間 | [0-9]+ |
18648689595962 |
| BLOB | 任何二進位制資料 | 任何 |
沒有布林型別。整數代替使用。
SELECT 查詢的完整語法如下
SELECT[ ALL| DISTINCT] <column name>[[ AS] <alias>][,[ ALL| DISTINCT] <column name>[[ AS] <alias>]]*
FROM <table>[[ AS] <alias>|[[ FULL| LEFT| RIGHT] OUTER| INNER] JOIN <table> ON <expression>]
[, <table>[[ AS] <alias>|[[ FULL| LEFT| RIGHT] OUTER| INNER] JOIN <table> ON <expression>]]*
[WHERE <predicate>[{ AND| OR} <predicate>]*]
[GROUP BY <column name>[, <column name>]*
[HAVING <predicate>[{ AND| OR} <predicate>]]*]
]
[ORDER BY <column name>[ ASC| DESC][, <column name>[ ASC| DESC]]*]
[FETCH FIRST <count> ROWS ONLY];
讓我們建立一個包含多個列的表格 reunion
| id_reunion | INTEGER |
| name | VARCHAR(20) |
| description | VARCHAR(255) |
| priority | CHAR(1) |
| planned | SMALLINT |
| date | DATE |
| hour | TIME |
| duration | INTEGER |
| # id_office | INTEGER |
| pdf_report | BLOB |
...讓我們填充它
| id_reunion | name | description | priority | planned | date | hour | duration | # id_office | pdf_report |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Planning | 我們需要計劃專案。 | A | 1 | 2008-03-24 | 10:30:00 | 60 | 35 | 48644...846348 |
| 2 | Progress | 我們做了什麼。 | C | 1 | 2008-05-12 | 14:00:00 | 30 | 13 | 9862...15676 |
| 3 | Change | 我們需要在專案中改變什麼。 | B | 1 | 2008-06-03 | 9:30:00 | 90 | 41 | 34876...4846548 |
| 4 | Presentation | 專案的展示。 | D | 0 | 2008-09-11 | 15:30:00 | 120 | 27 | |
| 5 | Reporting | 對新手進行解釋。 | B | 1 | 2009-03-15 | 14:00:00 | 60 | 7 | 19739...37718 |
| 6 | Learning | 已安裝新軟體版本。 | B | 1 | 2009-09-21 | 16:00:00 | 120 | 11 | 785278...37528 |
讓我們做一個簡單的查詢。以下查詢只返回 reunion 表的內容
- 查詢:
SELECT *
FROM reunion;
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |1 |Planning |We need to plan the project. |A |1 |2008-03-24 |10:30:00 |60 |35 |48644...846348 | |2 |Progress |What we have done. |C |1 |2008-05-12 |14:00:00 |30 |13 |9862...15676 | |3 |Change |What we need to change in the project. |B |1 |2008-06-03 |9:30:00 |90 |41 |34876...4846548 | |4 |Presentation |Presentation of the project. |D |0 |2008-09-11 |15:30:00 |120 |27 |NULL | |5 |Reporting |Explanation to the new beginner. |B |1 |2009-03-15 |14:00:00 |60 |7 |19739...37718 | |6 |Learning |A new software version has been installed. |B |1 |2009-09-21 |16:00:00 |120 |11 |785278...37528 | |----------------------------------------------------------------------------------------------------------------------------------------------------|
結果的形式取決於客戶端應用程式。它可以作為文字輸出(後端)、HTML 頁面(瘦客戶端)、程式物件(中介軟體)等返回... 語句、查詢、子句(SELECT、FROM...)、指令和運算子不區分大小寫,但它們通常用大寫字母書寫以提高可讀性。
SELECT 和 FROM 子句是 SELECT 查詢的兩個必需子句
- FROM : 列出查詢用於返回資料的表,
- SELECT : 列出要返回的資料。
WHERE 子句不影響查詢返回的列,而是影響行。它透過對行應用謂詞來過濾行。謂詞指定可以為真或假的條件。SQL 可以處理結果未知的條件。例如,以下查詢返回優先順序級別為 B 的重聚
- 查詢:
SELECT *
FROM reunion
WHERE reunion.priority = 'B';
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |3 |Change |What we need to change in the project. |B |1 |2008-06-03 |9:30:00 |90 |41 |34876...4846548 | |5 |Reporting |Explanation to the new beginner. |B |1 |2009-03-15 |14:00:00 |60 |7 |19739...37718 | |6 |Learning |A new software version has been installed. |B |1 |2009-09-21 |16:00:00 |120 |11 |785278...37528 | |----------------------------------------------------------------------------------------------------------------------------------------------------|
如果表名不含糊,則可以省略表名。
與第二個運算元相比,第一個運算元可以是
- 相等 :
= - 不同 :
<> - 小於 :
< - 小於或等於 :
<= - 大於 :
> - 大於或等於 :
>=
以下查詢返回優先順序級別不為 B 的重聚
- 查詢:
SELECT *
FROM reunion
WHERE priority <> 'B';
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |1 |Planning |We need to plan the project. |A |1 |2008-03-24 |10:30:00 |60 |35 |48644...846348 | |2 |Progress |What we have done. |C |1 |2008-05-12 |14:00:00 |30 |13 |9862...15676 | |4 |Presentation |Presentation of the project. |D |0 |2008-09-11 |15:30:00 |120 |27 |NULL | |----------------------------------------------------------------------------------------------------------------------------------------------------|
WHERE 子句可以使用 AND(所有條件都必須為真)和 OR(只有一個條件需要為真)運算子包含多個條件。OR 運算子是包含性的(多個條件可以為真)。括號可以指示求值的順序。NOT 會反轉一個條件。以下查詢返回優先順序級別為 B 並且持續時間超過一小時 或者在 2008/05/12 發生的重聚
- 查詢:
SELECT *
FROM reunion
WHERE (priority = 'B' AND NOT duration <= 60) OR date = '2008-05-12';
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |2 |Progress |What we have done. |C |1 |2008-05-12 |14:00:00 |30 |13 |9862...15676 | |3 |Change |What we need to change in the project. |B |1 |2008-06-03 |9:30:00 |90 |41 |34876...4846548 | |6 |Learning |A new software version has been installed. |B |1 |2009-09-21 |16:00:00 |120 |11 |785278...37528 | |----------------------------------------------------------------------------------------------------------------------------------------------------|
LIKE 允許簡化的正則表示式匹配。它可以應用於文字列(CHAR、VARCHAR 等)。
- 字母數字字元只匹配相同的文字,
%是一個萬用字元,匹配任何文字,_是一個萬用字元,匹配任何單個字元,
以下查詢返回以 "ing" 結尾且描述中包含 " the " 的重聚
- 查詢:
SELECT *
FROM reunion
WHERE name LIKE '%ing' AND description LIKE '% the %';
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |1 |Planning |We need to plan the project. |A |1 |2008-03-24 |10:30:00 |60 |35 |48644...846348 | |5 |Reporting |Explanation to the new beginner. |B |1 |2009-03-15 |14:00:00 |60 |7 |19739...37718 | |----------------------------------------------------------------------------------------------------------------------------------------------------|
BETWEEN 匹配可以是數字、日期或時間的範圍值。IN 匹配允許值的列表。以下查詢返回在 2008-04-01 和 2009-04-01 之間發生的並且優先順序級別為 A、B 或 D 的重聚
- 查詢:
SELECT *
FROM reunion
WHERE date BETWEEN '2008-04-01' AND '2009-04-01' AND priority IN ('A', 'B', 'D');
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |3 |Change |What we need to change in the project. |B |1 |2008-06-03 |9:30:00 |90 |41 |34876...4846548 | |4 |Presentation |Presentation of the project. |D |0 |2008-09-11 |15:30:00 |120 |27 |NULL | |5 |Reporting |Explanation to the new beginner. |B |1 |2009-03-15 |14:00:00 |60 |7 |19739...37718 | |----------------------------------------------------------------------------------------------------------------------------------------------------|
EXISTS 通常與子查詢一起使用。如果列表(即子查詢的結果集)不為空,則該謂詞為真。此關鍵字允許使用與返回行不直接關聯的資料(即它們未連線、未連結、未關聯... 返回的行),因此在這種情況下無法使用連線來過濾返回的行。例如,我們想要檢索所有至少有一個重聚是其他重聚的兩倍長的重聚
- 查詢:
SELECT *
FROM reunion r1
WHERE EXISTS (
SELECT r2.id_reunion
FROM reunion r2
WHERE r2.duration = r1.duration * 2
);
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |1 |Planning |We need to plan the project. |A |1 |2008-03-24 |10:30:00 |60 |35 |48644...846348 | |2 |Progress |What we have done. |C |1 |2008-05-12 |14:00:00 |30 |13 |9862...15676 | |5 |Reporting |Explanation to the new beginner. |B |1 |2009-03-15 |14:00:00 |60 |7 |19739...37718 | |----------------------------------------------------------------------------------------------------------------------------------------------------|
此查詢中使用了另一個重聚的持續時間,而這兩個行之間沒有連線、連結或關係。如果不使用 EXISTS,則無法完成此條件。請注意,子查詢使用別名 r1,而此別名是在主查詢中定義的。
EXISTS 也用於匹配缺少的資料。讓我們記住 employee 表和 members 表
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
以下查詢返回未連結到任何專案的員工(即 members 表中沒有他們關係的員工)
- 查詢:
SELECT *
FROM employees e
WHERE NOT EXISTS (
SELECT m.id_employee
FROM members m
WHERE m.id_employee = e.id_employee
);
- 結果:
|------------------------------------------------------------------| |id_employee |firstname |lastname |phone |mail | |------------|----------|---------|----------|---------------------| |1 |Big |BOSS |936854270 |big.boss@company.com | |------------------------------------------------------------------|
IS NULL 用於測試列是否已填充。它通常用於外部索引鍵列。
FROM 子句
[edit | edit source]FROM 子句定義用於查詢的表,但它也可以聯接表。JOIN 建立一個包含兩個表列的超級表,用於查詢。為了解釋聯接是什麼,我們考慮兩個沒有主鍵或外部索引鍵的古老表
|
| ||||||||||||||||||||||||||||||||
我們希望將來自不同表列的值關聯起來,這些值匹配每個表中給定列的值。
FULL OUTER JOIN
[edit | edit source]聯接是透過將一個表上的列與另一個表上的列進行匹配來實現的。在 FULL OUTER JOIN 之後,對於給定值(red),對於一個表上具有此值的給定行([ red | 9999 ]),將為另一個表上匹配的每一行建立一個行([ red | OOOOOO ] 和 [ red | LLLLLL ])。如果一個值僅存在於一個表中,則會建立一個行,並使用 NULL 列將其補全。
FROM table_1 FULL OUTER JOIN table_2 ON table_1.common_value = table_2.common_value
|
|
RIGHT OUTER JOIN
[edit | edit source]RIGHT OUTER JOIN 類似於 FULL OUTER JOIN,但它不會為左表中不存在的值建立行。
FROM table_1 RIGHT OUTER JOIN table_2 ON table_1.common_value = table_2.common_value
|
|
LEFT OUTER JOIN
[edit | edit source]LEFT OUTER JOIN 類似於 FULL OUTER JOIN,但它不會為右表中不存在的值建立行。
FROM table_1 LEFT OUTER JOIN table_2 ON table_1.common_value = table_2.common_value
|
|
INNER JOIN
[edit | edit source]INNER JOIN 類似於 FULL OUTER JOIN,但它僅為左表和右表中都存在的值建立行。
FROM table_1 INNER JOIN table_2 ON table_1.common_value = table_2.common_value
|
|
別名
[edit | edit source]FROM 子句可以宣告多個表,用,隔開,並且可以使用 AS 關鍵字為表名定義別名,這允許使用者使用相同的表進行多次聯接。以下查詢等同於上面的 INNER JOIN
- 查詢:
SELECT *
FROM table_1 AS t1, table_2 AS t2
WHERE t1.common_value = t2.common_value
AS 關鍵字可以省略。
SELECT 子句
[edit | edit source]SELECT 子句不影響查詢處理的資料,而是影響返回給使用者的資料。* 返回聯接和過濾後的所有處理資料。否則,SELECT 子句將列出用,隔開的表示式。
表示式可以是表名、表名和用點號隔開的列名,或者如果它不含糊則可以是簡單的列名。SELECT 子句還允許使用求值表示式,如加法、減法、串聯等。表示式後可以使用 AS 關鍵字後跟別名。AS 關鍵字可以省略。
以下是一個例子
- 查詢:
SELECT reunion.id_reunion, concat(name, ' : ', reunion.description) n, priority AS p, planned * 10 AS plan, duration + 10 AS reunion_length
FROM reunion;
- 結果:
|-------------------------------------------------------------------------------------------| |id_reunion |n |p |plan |reunion_length | |-----------|------------------------------------------------------|--|-----|---------------| |1 |Planning : We need to plan the project. |A |10 |70 | |2 |Progress : What we have done. |C |10 |40 | |3 |Change : What we need to change in the project. |B |10 |100 | |4 |Presentation : Presentation of the project. |D |0 |130 | |5 |Reporting : Explanation to the new beginner. |B |10 |70 | |6 |Learning : A new software version has been install... |B |10 |130 | |-------------------------------------------------------------------------------------------|
表示式也可以是以下聚合函式
count(*):返回行的數量。max(<column_name>):列的最大值。min(<column_name>):列的最小值。
以下是一個新的例子
- 查詢:
SELECT count(*) * 10 AS c, max(date) AS latest_date, min(reunion.date) oldest_date
FROM reunion;
- 結果:
|-----------------------------| |c |latest_date |oldest_date | |---|------------|------------| |60 |2009-09-21 |2008-03-24 | |-----------------------------|
ORDER BY 子句
[edit | edit source]ORDER BY 子句根據一個或多個列對查詢返回的行進行排序。排序使用第一個提到的列進行。第二個列用於對第一列中具有相同值的行進行排序,依此類推。可以在每個列之後新增 ASC 或 DESC 關鍵字。ASC 表示升序排序。DESC 表示降序排序。預設值為降序排序。讓我們執行兩個簡單的請求,第一個只按一個列排序,第二個按兩個列排序
- 查詢:
SELECT *
FROM reunion
ORDER BY priority ASC;
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |1 |Planning |We need to plan the project. |A |1 |2008-03-24 |10:30:00 |60 |35 |48644...846348 | |3 |Change |What we need to change in the project. |B |1 |2008-06-03 |9:30:00 |90 |41 |34876...4846548 | |5 |Reporting |Explanation to the new beginner. |B |1 |2009-03-15 |14:00:00 |60 |7 |19739...37718 | |6 |Learning |A new software version has been installed. |B |1 |2009-09-21 |16:00:00 |120 |11 |785278...37528 | |2 |Progress |What we have done. |C |1 |2008-05-12 |14:00:00 |30 |13 |9862...15676 | |4 |Presentation |Presentation of the project. |D |0 |2008-09-11 |15:30:00 |120 |27 |NULL | |----------------------------------------------------------------------------------------------------------------------------------------------------|
- 查詢:
SELECT *
FROM reunion
ORDER BY priority ASC, duration DESC;
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |1 |Planning |We need to plan the project. |A |1 |2008-03-24 |10:30:00 |60 |35 |48644...846348 | |6 |Learning |A new software version has been installed. |B |1 |2009-09-21 |16:00:00 |120 |11 |785278...37528 | |3 |Change |What we need to change in the project. |B |1 |2008-06-03 |9:30:00 |90 |41 |34876...4846548 | |5 |Reporting |Explanation to the new beginner. |B |1 |2009-03-15 |14:00:00 |60 |7 |19739...37718 | |2 |Progress |What we have done. |C |1 |2008-05-12 |14:00:00 |30 |13 |9862...15676 | |4 |Presentation |Presentation of the project. |D |0 |2008-09-11 |15:30:00 |120 |27 |NULL | |----------------------------------------------------------------------------------------------------------------------------------------------------|
GROUP BY 子句
[edit | edit source]GROUP BY 子句用於聚合操作。它將行收集到組中,例如,所有在給定列中具有相同值的行。在將行收集到組中之後,任何聚合操作都將應用於每個組,而不是一個唯一的大的行組。因此,聚合操作將返回與組數量一樣多的結果。組可以使用具有給定列中相同值的,或具有多個給定列中相同值的組合的所有行來形成。例如,我們想知道每個優先順序型別的聚會數量
- 查詢:
SELECT count(*) as number, priority
FROM reunion
GROUP BY priority;
- 結果:
|-----------------| |number |priority | |-------|---------| |1 |A | |3 |B | |1 |C | |1 |D | |-----------------|
由於 GROUP BY 子句,聚合函式 count(*) 不返回全域性計數,而是返回每個優先順序級別的計數(A、B、C 和 D)。
- 查詢:
SELECT count(*) as number, planned, duration
FROM reunion
GROUP BY planned, duration;
- 結果:
|--------------------------| |number |planned |duration | |-------|--------|---------| |1 |0 |120 | |1 |1 |30 | |2 |1 |60 | |1 |1 |90 | |1 |1 |120 | |--------------------------|
請注意,planned 列有四個值為 1 的組,duration 列有兩個值為 120 的組。但是,您可以看到沒有兩個列中具有相同值的組合的組。
HAVING 子句
[edit | edit source]HAVING 子句與 GROUP BY 子句一起使用。HAVING 子句包含一個謂詞,並從返回的行中刪除謂詞為假的組。例如,我們只想檢索至少有兩個具有相同優先順序級別的聚會的優先順序
- 查詢:
SELECT priority
FROM reunion
GROUP BY priority
HAVING count(*) > 1;
- 結果:
|---------| |priority | |---------| |B | |---------|
FETCH FIRST 子句
[edit | edit source]FETCH FIRST 子句用於限制返回行的數量。僅返回第一行。返回行的數量是在子句中指示的數量。
- 查詢:
SELECT *
FROM reunion
FETCH FIRST 4 ROWS ONLY;
- 結果:
|----------------------------------------------------------------------------------------------------------------------------------------------------| |id_reunion |name |description |priority |planned |date |hour |duration |id_office |pdf_report | |-----------|-------------|-------------------------------------------|---------|--------|-----------|---------|---------|----------|----------------| |1 |Planning |We need to plan the project. |A |1 |2008-03-24 |10:30:00 |60 |35 |48644...846348 | |2 |Progress |What we have done. |C |1 |2008-05-12 |14:00:00 |30 |13 |9862...15676 | |3 |Change |What we need to change in the project. |B |1 |2008-06-03 |9:30:00 |90 |41 |34876...4846548 | |4 |Presentation |Presentation of the project. |D |0 |2008-09-11 |15:30:00 |120 |27 |NULL | |----------------------------------------------------------------------------------------------------------------------------------------------------|
此子句通常用於不返回測試中無用的行或提高效能。
現在您可以探索現有資料庫中的所有資料。
SQL 函式
[edit | edit source]- COUNT
- AVG
- MIN
- MAX
- SUM
例如
SELECT '''COUNT(*)''' FROM reunion
返回表 reunion 中的行數。
---
- 另請參見:[[1]]