Linux 必掌握的 SQL 命令

數據庫和 SQLmysql

在本系列教程中,目前咱們使用平面文本文件來存儲數據。平面文本文件可能適合相對較少的數據,但它們對存儲大量數據或查詢該數據沒有多大幫助。多年來,爲該目的開發了多種數據庫,包括分層和網絡數據庫,但如今最多見的是關係數據庫。關係數據庫基於 E. F. Codd 的想法,E. F. Codd 效力於 IBM®,他在 1970 年發表了原創性論文 「一種針對大型共享數據銀行的關係數據模型」。現在有多種關係數據庫系統,包括商用產品(好比 IBM DB2®、IBM Informix® 和 Oracle Database)和開源項目(好比 MySQL、PostgreSQL SQLite 和 MariaDB[MySQL 的一個分支])。關係數據庫使用 SQL 做爲數據定義和查詢語言。linux


Linux 必掌握的 SQL 命令Linux 必掌握的 SQL 命令

前提條件正則表達式

要從本系列教程中得到最大收穫,您應該擁有 Linux 的基本知識和一個正常工做的 Linux 系統,您能夠在這個系統上實踐本教程中涵蓋的命令。您應該熟悉 GNU 和 UNIX® 命令。有時,一個程序的不一樣版本會以不一樣方式格式化輸出,因此您的結果可能並不老是與這裏給出的清單徹底同樣。sql

對於本教程,您須要一個數據庫(好比 MariaDB)和您的數據庫的文檔。shell


Linux 必掌握的 SQL 命令Linux 必掌握的 SQL 命令
本教程中的 SQL 示例在很大程度上獨立於發行版和數據庫。大部分示例都使用了含 4.2.6 內核的 Fedora 23 上的開源 MariaDB 10.0.21 版。我還提供了一些使用 IBM DB2 Express-C 10.5 版的示例,該版本是 IBM DB2 數據服務器在含 2.6.32 內核的 CentOS 6.7 上的一個免費社區版本。經過比較這些示例,您能夠了解您在使用多種數據庫系統時可能遇到的差異。若是您須要實現可移植的數據庫程序或腳本,則要求您對 ISO/ANSI SQL 標準的瞭解比我在這裏介紹的多一些。數據庫

一些數據庫操做命令是特定於數據庫的。SQL 語法中也存在一些小差別,尤爲是對於非標準擴展。在必要時,請參閱您使用的數據庫的文檔。bash

數據庫、表、列和行服務器

關係數據庫由一組表 組成。能夠將表中的每行 數據視爲一條記錄,表的每列 對應於相應行的記錄中的字段。一列中的數據都具備相同的類型,好比字符、整數、日期或二進制數據(好比圖像)。經過以這種方式使用結構化數據,您能夠構造有益的查詢,好比 「找到在某個日期後招聘的全部員工」 或 「找到全部大於 0.25 英畝的地塊」。網絡

關係數據庫中的數據可能在每行有一個惟一值,好比員工記錄中的員工 ID,市政土地數據庫中的地塊 ID,或者計算機系統中的用戶 ID。若是是這樣,您能夠爲該列建立一個索引,能夠將一個這樣的列指定爲該表的主鍵。鍵和索引可幫助數據庫引擎加速數據的檢索。less

當您安裝數據庫時,您一般會安裝一個數據庫服務器。您可能還會安裝一個客戶端,或者可能經過編寫的應用程序或命令行訪問該服務器。服務器一般做爲後臺進程運行,您的客戶端或應用程序一般經過 TCP/IP 鏈接來鏈接它。您必須採起相應的措施來保護安裝,預防您不想支持的訪問。


Linux 必掌握的 SQL 命令Linux 必掌握的 SQL 命令

許多 Linux 發行版包含 MariaDB、SQLite、PostgreSQL 和 MySQL 的包。對於本教程,我主要使用了 MariaDB。請參閱 「包含 MariaDB 的發行版」 或使用適合您的發行版的包管理工具來檢查已爲您的發行版打包了哪些數據庫。MariaDB 是 MySQL 的一個開源分支,因此 mysql 是許多命令名稱的一部分。

MariaDB 入門

這裏提供一些簡單技巧,幫助您在打包了 MariaDB 的發行版上運行它。我在本教程中使用了 Fedora 23。首先安裝 mariadb 和 mariadb-server 包,它們會引入所需的其餘一些包。

接下來,採用擁有 root 用戶權限的用戶身份運行 mysql_secure_installation 命令。經過運行此命令,您能夠:

爲一個 root 數據庫用戶設置一個密碼
刪除最初安裝用於測試的匿名用戶
確保該 root 用戶僅能從本地系統登陸
刪除測試數據庫(可選)
從新加載特權表,讓以前的更改當即生效

數據庫 root 用戶不是系統 root 用戶,不該擁有相同的密碼。若是您須要執行更改,能夠從新運行 mysql_secure_installation。
對於本教程,我使用了來自 GitHub 的 test_db 包中包含的 employee 示例數據庫。清單 1 給出了我將該數據庫安裝在個人系統上所用的步驟。

清單 1. 安裝示例 employee 數據庫

[ian@attic-f23 ~]$ unzip -q test_db-master.zip 
[ian@attic-f23 ~]$ cd test_db-master
[ian@attic-f23 test_db-master]$ mysql -u root -p (< )employees .sql
Enter password: 
INFO
CREATING DATABASE STRUCTURE
INFO
storage engine: InnoDB
INFO
LOADING departments
INFO
LOADING employees
INFO
LOADING dept_emp
INFO
LOADING dept_manager
INFO
LOADING titles
INFO
LOADING salaries
data_load_time_diff
NULL.

清單 1 中使用的默認 InnoDB 引擎適合本教程的目的。

您的第一個數據庫

如今 MariaDB 已安裝在您的系統上,您能夠啓動它來看看您擁有哪些數據庫。清單 2 使用 mysqlshow 命令來顯示我已安裝的數據庫。-u 選項指定數據庫 root 用戶,-p 選項告訴 mysqlshow 提示您輸入您在運行 mysql_secure_installation 命令時定義的密碼。

清單 2. 我擁有哪些數據庫?

[ian@attic-f23 ~]$ mysqlshow -u root -p
Enter password: 
+--------------------+
|     Databases      |
+--------------------+
| employees          |
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+

能夠看到我有 5 個數據庫:我剛剛建立的 employees 數據庫,我沒有建立的 test 數據庫,以及其餘 3 個數據庫。數據庫程序一般包含多個數據庫來描述該數據庫自己,您能夠在 清單 2 中看到它們。

mysqlshow 命令是一個快速列出數據庫、表和列信息的便捷工具。MariaDB(和 MySQL)包含一個相似於數據庫 shell 的交互式命令行接口 (CLI) 程序,名爲 mysql。DB2 還有一個 CLI 程序,名爲 db2。與 bash 等 shell 同樣,您能夠將一個命令傳遞到任意一個數據庫 shell,也能夠運行一個包含許多命令的交互式會話。清單 3 經過帶 -e 選項的 mysql 命令執行單個數據庫命令來顯示數據庫信息。

清單 3. 列出 MariaDB 數據庫

[ian@attic-f23 ~]$ mysql -u root -p -e "show databases"
Enter password: 
+--------------------+
| Database           |
+--------------------+
| employees          |
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+

若是您還安裝了 DB2 Express-C,那麼您已經建立了一個名爲 db2inst1 的用戶(默認用戶)來管理該數據庫。清單 4 展現瞭如何使用 db2 命令獲取 DB2 數據庫的相應信息。

清單 4. 列出 DB2 數據庫

[ian@attic4-cent ~]$ db2 list database directory

 System Database Directory

 Number of entries in the directory = 1

Database 1 entry:

 Database alias                       = SAMPLE
 Database name                        = SAMPLE
 Local database directory             = /home/db2inst1
 Database release level               = 10.00
 Comment                              =
 Directory entry type                 = Indirect
 Catalog database partition number    = 0
 Alternate server hostname            =
 Alternate server port number         =

瞭解表和列

在從數據庫提取信息以前,您須要知道數據庫中有什麼。在 清單 5 中,您能夠了解如何:

啓動 mysql 交互式數據庫 shell,並使用您建立的 root ID 鏈接到 employees 數據庫
使用 show tables 命令查看 employees 數據庫中包含哪些表
使用 describe 命令查看 employees 數據庫中的 employees 表中包含哪些列

清單 5. 顯示 MariaDB 表和列信息

[ian@attic-f23 ~]$ mysql -u root -p employees
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 19
Server version: 10.0.21-MariaDB MariaDB Server

Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [employees]> show tables;
+----------------------+
| Tables_in_employees  |
+----------------------+
| current_dept_emp     |
| departments          |
| dept_emp             |
| dept_emp_latest_date |
| dept_manager         |
| employees            |
| salaries             |
| titles               |
+----------------------+
8 rows in set (0.00 sec)

MariaDB [employees]> describe employees;
+------------+---------------+------+-----+---------+-------+
| Field      | Type          | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| emp_no     | int(11)       | NO   | PRI | NULL    |       |
| birth_date | date          | NO   |     | NULL    |       |
| first_name | varchar(14)   | NO   |     | NULL    |       |
| last_name  | varchar(16)   | NO   |     | NULL    |       |
| gender     | enum('M','F') | NO   |     | NULL    |       |
| hire_date  | date          | NO   |     | NULL    |       |
+------------+---------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

employees 表中的每一個字段(或列)有多個屬性:

Field:列的名稱。
Type:列的數據類型。許多數據類型都具備最大長度限制。例如,int(11) 指定一個可包含 11 位數的整數,varchar(16) 指定包含最多 16 字節數據的可變長度字符串。請參閱 「SQL 數據類型」 部分,瞭解有關數據類型的更多信息。
Null:指定是否容許該列擁有 null(空)值。
Key:若是該列是一個鍵,則表示鍵類型。主 (PRI) 鍵必須包含非 null 的惟一值。
Default:指定若是添加一條記錄且沒有爲該列提供數據,則在該列中放入什麼樣的默認值。
Extra:指定額外屬性(例如 auto_increment,它用於建立惟一遞增編號,好比序列號)。

若是您在 shell 中須要得到幫助,可使用 help(或 ?)命令。清單 6 給出了 describe 命令的幫助輸出。

清單 6. MariaDB describe 命令的幫助

MariaDB [employees]> ? describe
Name: 'DESCRIBE'
Description:
Syntax:
{DESCRIBE | DESC} tbl_name [col_name | wild]

DESCRIBE provides information about the columns in a table. It is a
shortcut for SHOW COLUMNS FROM. These statements also display
information for views. (See [HELP SHOW COLUMNS].)

col_name can be a column name, or a string containing the SQL "%" and
"_" wildcard characters to obtain output only for the columns with
names matching the string. There is no need to enclose the string
within quotation marks unless it contains spaces or other special
characters.

MariaDB> DESCRIBE City;
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| Id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name       | char(35) | NO   |     |         |                |
| Country    | char(3)  | NO   | UNI |         |                |
| District   | char(20) | YES  | MUL |         |                |
| Population | int(11)  | NO   |     | 0       |                |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

The description for SHOW COLUMNS provides more information about the
output columns (see [HELP SHOW COLUMNS]).

URL: https://mariadb.com/kb/en/describe/

請注意,該幫助以全大寫字母形式顯示 DESCRIBE。一般,SQL 命令名稱是不區分大小寫的。其餘對象(好比數據庫、表或列)的名稱是否區分大小寫取決於您的數據庫程序和運行它的平臺。請參見 參考資料,瞭解有關 MariaDB 的更多信息。

SQL 數據類型

您已在 清單 5 中看到了 SQL 數據類型的示例。典型的 SQL 數據類型大致分爲 4 類:

String 數據類型存儲固定長度或可變長度的字符或二進制串,以及大對象。示例包括 CHAR(8)、VARCHAR(240)、BINARY(12)、VARBINARY(500) 和 BLOB(200000)。
Numeric 數據類型存儲定點數或浮點數。示例包括 SMALLINT(16 位)、INT 或 INTEGER(32 位)、BIGINT(64 位)、FLOAT(單精度浮點)、DOUBLE(雙精度浮點)和 DECIMAL(一個包含小數點的壓縮十進制數)。整數數據能夠是有符號或無符號的。
Boolean 數據類型存儲 TRUE 或 FALSE 值。
Date 和 time 值存儲可用於比較的日期和時間。示例包括 DATE 和 TIME。

這些示例並不詳盡,並且不一樣的數據庫程序可能會擴展它們。例如,DB2 支持使用 CLOB 存儲字符大對象,使用 DBCLOB 存儲包含雙字節字符數據的大對象。MariaDB 支持使用 TINYINT 存儲 1 字節整數和使用 ENUM 存儲枚舉數據,您在 清單 5 中的 gender 字段中已看到。
備註:在 SQL 中使用枚舉數據類型存在必定的爭議。更傳統的方法是使用具備外鍵 的參考表。能夠在網絡上搜索來進一步瞭解對數據庫中的枚舉數據類型的爭議。

從表中選擇數據

您如今已經看到了數據庫、表和表中的數據類型的示例。下一步是獲取表中的數據。可使用 SELECT 語句檢索數據。能夠選擇表中的全部數據,或者選擇特定列的數據。清單 7 顯示了 departments 表中的數據,以及如何經過 SELECT * 選擇其中的全部數據,而後如何僅選擇部門名稱。

清單 7. SELECT 命令的基本用法

MariaDB [employees]> describe departments;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| dept_no   | char(4)     | NO   | PRI | NULL    |       |
| dept_name | varchar(40) | NO   | UNI | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

MariaDB [employees]> select * from departments;
+---------+--------------------+
| dept_no | dept_name          |
+---------+--------------------+
| d009    | Customer Service   |
| d005    | Development        |
| d002    | Finance            |
| d003    | Human Resources    |
| d001    | Marketing          |
| d004    | Production         |
| d006    | Quality Management |
| d008    | Research           |
| d007    | Sales              |
+---------+--------------------+
9 rows in set (0.00 sec)

MariaDB [employees]> select dept_name from departments;
+--------------------+
| dept_name          |
+--------------------+
| Customer Service   |
| Development        |
| Finance            |
| Human Resources    |
| Marketing          |
| Production         |
| Quality Management |
| Research           |
| Sales              |
+--------------------+
9 rows in set (0.00 sec)

排序和選擇

選擇 departments 表中的全部數據時,像 清單 7 中同樣,輸出會按部門名稱排序。若是您但願根據一個或多個列中的值對輸出數據進行排序,可使用 ORDER BY 子句。指定一個用逗號分隔的列組成的列表。也能夠指定 ASC 來按升序進行排序(默認),或者指定 DESC 來按照降序進行排序。清單 8 展現瞭如何按 dept_no 進行降序排序。

清單 8. 對查詢輸出進行排序

MariaDB [employees]> select dept_name,dept_no from departments order by dept_no desc;
+--------------------+---------+
| dept_name          | dept_no |
+--------------------+---------+
| Customer Service   | d009    |
| Research           | d008    |
| Sales              | d007    |
| Quality Management | d006    |
| Development        | d005    |
| Production         | d004    |
| Human Resources    | d003    |
| Finance            | d002    |
| Marketing          | d001    |
+--------------------+---------+
9 rows in set (0.00 sec)

可使用 WHERE 子句選擇要顯示哪些數據。能夠比較各列,或者將列值與某個值比較。該值(稱爲標量)能夠是一個常數(必須包含在引號內)或一個標量函數的結果,好比今天的日期。可以使用布爾 AND、OR 和 NOT 運算符來定義更復雜的條件。清單 9 給出了一些使用 departments 表的示例。

清單 9. 使用 WHERE 子句限制數據輸出

MariaDB [employees]> select * from departments where dept_no > 'd007';
+---------+------------------+
| dept_no | dept_name        |
+---------+------------------+
| d008    | Research         |
| d009    | Customer Service |
+---------+------------------+
2 rows in set (0.00 sec)

MariaDB [employees]> select * from departments
    -> WHERE dept_name = 'Customer Service' OR (
    -> dept_no > 'd002' AND dept_no < = "d006" -> );
+---------+--------------------+
| dept_no | dept_name          |
+---------+--------------------+
| d009    | Customer Service   |
| d005    | Development        |
| d003    | Human Resources    |
| d004    | Production         |
| d006    | Quality Management |
+---------+--------------------+
5 rows in set (0.00 sec)

請注意,在 清單 9 中,來自更復雜的 WHERE 子句的輸出沒有排序。使用 ORDER 子句來採用您想要的排序方式。另請注意,您能夠將 SQL 命令輸入在多行上。MariaDB 在第二行和後續行上提供了一個 -> 提示符。我在後續示例中刪除了這些輔助提示符,以便您能夠更輕鬆地將該命令直接複製並粘貼到本身的系統中。
您還可使用 LIKE 來執行模式匹配和直接比較。大多數 SQL 數據庫都支持如下兩種通配符:

% 匹配任意多個字符,包括空字符串。
_ 匹配任何單一字符。

清單 10 展現瞭如何查找全部包含字符串 es 的部門名稱。

清單 10. 使用 WHERE 子句和 LIKE 進行模式匹配

MariaDB [employees]> select * from departments WHERE dept_name LIKE '%es%';
+---------+-----------------+
| dept_no | dept_name       |
+---------+-----------------+
| d003    | Human Resources |
| d008    | Research        |
| d007    | Sales           |
+---------+-----------------+
3 rows in set (0.00 sec)v

一些數據庫(包括 MariaDB)支持正則表達式模式匹配。請參閱您數據庫的文檔,瞭解關於這個主題的更多信息。

針對列的 SQL 函數

您已經瞭解了一些簡單的比較運算符。SQL 還有一些函數可供使用,它們包括:

COUNT:統計返回的行數。
DISTINCT:僅選擇不一樣的值。
MAX 和 MIN:選擇一對值中的最大值或最小值。
NOW:返回當前的日期和時間。
DATEDIFF:將兩個日期相減,返回它們之間相隔的天數。
DAY:返回給定日期是星期幾。
LEAST:找到一組值中最小的一個值。

還有其餘許多這樣的函數,因此請參閱您的文檔來了解它們。
清單 11 展現瞭如何統計兩個不一樣表中的行數。

清單 11. 使用 COUNT 統計一個表中的行數

MariaDB [employees]> # How many employees?
MariaDB [employees]> select count(*) from employees;
+----------+
| count(*) |
+----------+
|   300024 |
+----------+
1 row in set (0.08 sec)

MariaDB [employees]> # How many managers?
MariaDB [employees]> select count(*) from dept_manager;
+----------+
| count(*) |
+----------+
|       24 |
+----------+
1 row in set (0.00 sec)

清單 12 展現瞭如何使用 DISTINCT 函數來查看一些經理是否與其餘經理在同一日期招聘的。

清單 12. 找到不一樣的開始日期

MariaDB [employees]> describe dept_manager;
+-----------+---------+------+-----+---------+-------+
| Field     | Type    | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no    | int(11) | NO   | PRI | NULL    |       |
| dept_no   | char(4) | NO   | PRI | NULL    |       |
| from_date | date    | NO   |     | NULL    |       |
| to_date   | date    | NO   |     | NULL    |       |
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)

MariaDB [employees]> select DISTINCT(from_date) from dept_manager order by from_date;
+------------+
| from_date  |
+------------+
| 1985-01-01 |
| 1988-09-09 |
| 1988-10-17 |
| 1989-05-06 |
| 1989-12-17 |
| 1991-03-07 |
| 1991-04-08 |
| 1991-09-12 |
| 1991-10-01 |
| 1992-03-21 |
| 1992-04-25 |
| 1992-08-02 |
| 1992-09-08 |
| 1994-06-28 |
| 1996-01-03 |
| 1996-08-30 |
+------------+
16 rows in set (0.00 sec)

僅返回了 16 行。您能夠組合 COUNT 和 DISTINCT 來得到此數字,但您在 清單 12 中也有實際的開始日期。您對多個經理開始上任的日期還一無所知。

假設您想找到某位經理上任了多長時間。能夠計算 from_date 與 to_date 的差,可是如何將此運算應用於目前正在任職的經理?表一般使用某種標記來表示當前日期,該日期也許是一個 NULL 值,也許是將來的一個日期。dept_manager 表使用一個將來的日期實現此目的。to_date 晚於今日表示該經理仍在任職。可以使用 NOW 函數得到當前的時間戳,或者使用 CURDATE 函數僅獲取當前日期。清單 13 展現了一種查找每位經理任職多少天的方式。

清單 13. 查找經理任職了多少天

MariaDB [employees]> # Show marker for managers still managing
MariaDB [employees]> select max(to_date) from dept_manager;
+--------------+
| max(to_date) |
+--------------+
| 9999-01-01   |
+--------------+
1 row in set (0.00 sec)

MariaDB [employees]> # Calculate duration of management in days
MariaDB [employees]> select emp_no, 
     datediff(least(to_date, curdate()),from_date)
     from dept_manager;
+--------+-----------------------------------------------+
| emp_no | datediff(least(to_date, curdate()),from_date) |
+--------+-----------------------------------------------+
| 110022 |                                          2464 |
| 110039 |                                          8869 |
| 110085 |                                          1811 |
| 110114 |                                          9522 |
| 110183 |                                          2636 |
| 110228 |                                          8697 |
| 110303 |                                          1347 |
| 110344 |                                          1423 |
| 110386 |                                          1489 |
| 110420 |                                          7074 |
| 110511 |                                          2671 |
| 110567 |                                          8662 |
| 110725 |                                          1586 |
| 110765 |                                           859 |
| 110800 |                                          1020 |
| 110854 |                                          7868 |
| 111035 |                                          2256 |
| 111133 |                                          9077 |
| 111400 |                                          2288 |
| 111534 |                                          9045 |
| 111692 |                                          1385 |
| 111784 |                                          1422 |
| 111877 |                                          1212 |
| 111939 |                                          7314 |
+--------+-----------------------------------------------+
24 rows in set (0.00 sec)

使用別名

當您擁有長表達式時,好比 datediff(least(to_date,curdate()),from_date),您可能但願縮短列標題或爲該表達式提供一個別名,由於您計劃在查詢中的其餘地方使用它,例如在 WHERE 子句中。清單 14 展現瞭如何使用別名來提供更短的標題,查找全部現任經理任職了多少年。

清單 14. 使用別名表示更短的標題

MariaDB [employees]> select emp_no AS Employee, 
     (datediff(least(to_date, curdate()),from_date)/365.25) as Years
     from dept_manager where to_date > curdate();
+----------+---------+
| Employee | Years   |
+----------+---------+
|   110039 | 24.2820 |
|   110114 | 26.0698 |
|   110228 | 23.8111 |
|   110420 | 19.3676 |
|   110567 | 23.7153 |
|   110854 | 21.5414 |
|   111133 | 24.8515 |
|   111534 | 24.7639 |
|   111939 | 20.0246 |
+----------+---------+
9 rows in set (0.00 sec)

使用 GROUP BY 對數據進行分組

有時您想彙總來自某個表的信息。例如,您想知道在每一個 10000 美圓薪資區間內有多少員工。爲此,可使用 GROUP BY 子句對您的數據進行分組。清單 15 展現瞭如何作。

清單 15. 使用 GROUP BY 聚合數據

MariaDB [employees]> describe salaries;
+-----------+---------+------+-----+---------+-------+
| Field     | Type    | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no    | int(11) | NO   | PRI | NULL    |       |
| salary    | int(11) | NO   |     | NULL    |       |
| from_date | date    | NO   | PRI | NULL    |       |
| to_date   | date    | NO   |     | NULL    |       |
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)

MariaDB [employees]> select salary DIV 10000 as 10K, count(*) as Number 
     from salaries where to_date > curdate() group by 10K;
+------+--------+
| 10K  | Number |
+------+--------+
|    3 |     85 |
|    4 |  20220 |
|    5 |  44666 |
|    6 |  56236 |
|    7 |  49128 |
|    8 |  32351 |
|    9 |  19939 |
|   10 |  10611 |
|   11 |   4729 |
|   12 |   1645 |
|   13 |    421 |
|   14 |     78 |
|   15 |     15 |
+------+--------+
13 rows in set (1.42 sec)

使用 HAVING 執行進一步選擇

在 清單 15 中,Number 列中的值是從聚合數據計算出來的。假設您僅對該範圍中擁有 5,000 或更少員工的薪資範圍感興趣。您的第一個想法多是使用 WHERE 子句,但您不能使用它得到計算爲聚合數據的中間結果數據。您須要使用 HAVING 子句,將中間結果限制到一個具備特定條件或條件組合的子集。清單 16 展現瞭如何查找該範圍中擁有 5,000 或更少員工的薪資範圍。

清單 16. 使用 HAVING 子句

MariaDB [employees]> select salary DIV 10000 as 10K, count(*) as Number 
     from salaries where to_date > curdate() group by 10K
     HAVING Number < = 5000;
+------+--------+
| 10K  | Number |
+------+--------+
|    3 |     85 |
|   11 |   4729 |
|   12 |   1645 |
|   13 |    421 |
|   14 |     78 |
|   15 |     15 |
+------+--------+
6 rows in set (1.45 sec)

使用 JOIN 從多個表獲取數據

目前爲止,本教程中的示例都使用了單個表。salaries 表和 dept_manager 表包含員工編號,但不含姓名或其餘員工信息。員工信息保存在 employees 表中。經過將數據保存在單獨的表中,SQL 設計能夠消除(或者至少減小)數據存儲冗餘,以及在一個位置更新數據而不在另外一個位置更新的相關風險。

在您想提取信息時,好比全部現任經理的姓名和性別,您須要從 dept_manager 表和 employees 表獲取此信息。出於這個目的,您使用 JOIN 子句和一個指定聯接 (join) 條件的條件表達式。最多見的是,您將兩個表聯接在單個字段上,該字段值在兩個表中相同,例如,dept_manager 表和 employees 表中都包含的 emp_no 字段。

清單 17 展現瞭如何使用 JOIN 查找全部現任經理的姓名和性別。(請注意,咱們使用了別名 e 和 m 來表示 dept_manager 表和 employees 表。)

清單 17. 使用 JOIN 子句獲取現任經理信息

MariaDB [employees]> SELECT e.first_name, e.last_name, e.gender 
     FROM employees as e JOIN dept_manager as m
     ON e.emp_no = m.emp_no
     WHERE m.to_date > now()
     ORDER BY e.last_name;
+------------+------------+--------+
| first_name | last_name  | gender |
+------------+------------+--------+
| Leon       | DasSarma   | F      |
| Oscar      | Ghazalie   | M      |
| Hilary     | Kambil     | F      |
| Isamu      | Legleitner | F      |
| Vishwani   | Minakawa   | M      |
| Dung       | Pesch      | M      |
| Karsten    | Sigstam    | F      |
| Yuchang    | Weedman    | M      |
| Hauke      | Zhang      | M      |
+------------+------------+--------+
9 rows in set (0.00 sec)

若是您想要使用薪資而不是性別做爲輸出列,必須將 salaries 表與其餘兩個表聯接,如 清單 18 所示。(我添加了一些括號,我發現括號對構造複雜查詢一般頗有用。)

清單 18. 使用 JOIN 子句獲取現任經理薪資

MariaDB [employees]> SELECT e.first_name, e.last_name, s.salary 
     FROM (employees as e JOIN dept_manager as m ON e.emp_no = m.emp_no)
     JOIN salaries as s on e.emp_no = s.emp_no
     WHERE m.to_date > now() AND s.to_date > now()
     ORDER BY e.last_name;
+------------+------------+--------+
| first_name | last_name  | salary |
+------------+------------+--------+
| Leon       | DasSarma   |  74510 |
| Oscar      | Ghazalie   |  56654 |
| Hilary     | Kambil     |  79393 |
| Isamu      | Legleitner |  83457 |
| Vishwani   | Minakawa   | 106491 |
| Dung       | Pesch      |  72876 |
| Karsten    | Sigstam    |  65400 |
| Yuchang    | Weedman    |  58745 |
| Hauke      | Zhang      | 101987 |
+------------+------------+--------+
9 rows in set (0.00 sec)

清單 17 和 清單 18 中的 JOIN 示例稱爲內部 聯接:它們從兩個表中查找與聯接條件匹配的行。另外 3 種常見的聯接是:

LEFT JOIN 查找左側表中的全部行和右側表中與該聯接條件匹配的行。
RIGHT JOIN 查找右側表中的全部行和左側表中與該聯接條件匹配的行。
OUTER JOIN 組合 LEFT JOIN 和 RIGHT JOIN 的結果。許多數據庫(包括 IBM DB2)將此稱爲 FULL OUTER JOIN。

INNER JOIN 最經常使用,並且是沒有指定聯接類型時的默認選擇。清單 19 演示瞭如何使用 LEFT JOIN 來顯示選定的員工,若是他們剛好是經理,則顯示他們的 from_date 和 to_date。在這個示例中,我還使用了 LIMIT 值將輸出限制爲最多 15 行。

清單 19. 使用 LEFT JOIN 子句

MariaDB [employees]> SELECT e.emp_no, e.first_name, e.last_name, s.salary, m.from_date, m.to_date 
     FROM (employees as e LEFT JOIN dept_manager as m ON e.emp_no = m.emp_no) 
     JOIN salaries as s on e.emp_no = s.emp_no AND s.to_date > now()
     WHERE e.last_name LIKE 'Kambi%' AND e.first_name > 'G' 
     ORDER BY e.last_name, e.first_name limit 15;
+--------+------------+-----------+--------+------------+------------+
| emp_no | first_name | last_name | salary | from_date  | to_date    |
+--------+------------+-----------+--------+------------+------------+
| 431582 | Gaurav     | Kambil    | 118128 | NULL       | NULL       |
| 252478 | Gaurav     | Kambil    |  69516 | NULL       | NULL       |
| 487991 | Gift       | Kambil    | 115960 | NULL       | NULL       |
| 204311 | Gil        | Kambil    |  96756 | NULL       | NULL       |
| 416604 | Gonzalo    | Kambil    |  80009 | NULL       | NULL       |
| 236164 | Hausi      | Kambil    |  66130 | NULL       | NULL       |
| 412003 | Hausi      | Kambil    |  83213 | NULL       | NULL       |
| 111534 | Hilary     | Kambil    |  79393 | 1991-04-08 | 9999-01-01 |
| 295702 | Huei       | Kambil    |  49498 | NULL       | NULL       |
|  77408 | Idoia      | Kambil    |  67122 | NULL       | NULL       |
| 271049 | Jianhao    | Kambil    |  58393 | NULL       | NULL       |
| 216820 | JiYoung    | Kambil    |  87541 | NULL       | NULL       |
| 206261 | Jongsuk    | Kambil    |  78396 | NULL       | NULL       |
| 250164 | Josyula    | Kambil    |  98835 | NULL       | NULL       |
| 289558 | Jouko      | Kambil    |  51393 | NULL       | NULL       |
+--------+------------+-----------+--------+------------+------------+
15 rows in set (0.14 sec)

使用子選擇

有時您僅對查詢中的部分數據感興趣,但願僅操做這部分數據。出於此目的,您可使用子選擇(也稱爲子查詢),它實質上是 SELECT 中的另外一個 SELECT。您還能夠在 FROM、WHERE 或 HAVING 子句中使用子選擇。有時經過子選擇完成的工做也能夠經過 JOIN 完成。考慮到如此多的選擇性,我將展現兩個示例來讓您瞭解這些。

employees 數據庫中的 titles 表顯示了一位員工已擔任的職位。一些員工擔任了多個職位。清單 20 展現瞭如何找到 3 位員工擔任的職位。請注意,咱們使用了 IN 運算符來從一個集合中選擇結果,使用了 BETWEEN 運算符來選擇兩個值之間的員工數。

清單 20. 擔任了不一樣職位的員工

MariaDB [employees]> describe titles;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| emp_no    | int(11)     | NO   | PRI | NULL    |       |
| title     | varchar(50) | NO   | PRI | NULL    |       |
| from_date | date        | NO   | PRI | NULL    |       |
| to_date   | date        | YES  |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

MariaDB [employees]> select * from titles  where emp_no IN (10001, 10004, 499666);

+--------+--------------------+------------+------------+
| emp_no | title              | from_date  | to_date    |
+--------+--------------------+------------+------------+
|  10001 | Senior Engineer    | 1986-06-26 | 9999-01-01 |
|  10004 | Engineer           | 1986-12-01 | 1995-12-01 |
|  10004 | Senior Engineer    | 1995-12-01 | 9999-01-01 |
| 499666 | Assistant Engineer | 1987-10-18 | 1994-10-18 |
| 499666 | Engineer           | 1994-10-18 | 2001-10-18 |
| 499666 | Senior Engineer    | 2001-10-18 | 9999-01-01 |
+--------+--------------------+------------+------------+
6 rows in set (0.00 sec)

MariaDB [employees]> select * from titles  where emp_no BETWEEN 10001 AND 10004; 
+--------+-----------------+------------+------------+
| emp_no | title           | from_date  | to_date    |
+--------+-----------------+------------+------------+
|  10001 | Senior Engineer | 1986-06-26 | 9999-01-01 |
|  10002 | Staff           | 1996-08-03 | 9999-01-01 |
|  10003 | Senior Engineer | 1995-12-03 | 9999-01-01 |
|  10004 | Engineer        | 1986-12-01 | 1995-12-01 |
|  10004 | Senior Engineer | 1995-12-01 | 9999-01-01 |
+--------+-----------------+------------+------------+
5 rows in set (0.01 sec)

您已經知道如何使用 GROUP BY 和 COUNT 來查找每位員工擔任過多少個職位。若是隻想知道多少員工擔任過一個職位,多少員工擔任過兩個職位等,該如何作? 清單 21 展現瞭如何構造一個查詢來查找每位員工擔任的職位數,而後如何使用此查詢做爲一個查詢的子選擇,回答多少員工擔任過一個職位,多少員工擔任過兩個職位等問題。我將這個子查詢命名爲 subq。該子查詢只返回一列:jobs。主要查詢使用限定名稱 subq.jobs 來引用此列。

清單 21. 使用子選擇來查找多少員工擔任過多個職位

MariaDB [employees]> SELECT count(*) as jobs from titles group by emp_no limit 5;
+------+
| jobs |
+------+
|    1 |
|    1 |
|    1 |
|    2 |
|    2 |
+------+
5 rows in set (0.00 sec)

MariaDB [employees]> SELECT jobs as '# jobs', count(subq.jobs) as '# employees'
     FROM (
     SELECT count(*) as jobs from titles group by emp_no 
     ) subq
     group by jobs;
+--------+-------------+
| # jobs | # employees |
+--------+-------------+
|      1 |      159754 |
|      2 |      137256 |
|      3 |        3014 |
+--------+-------------+
3 rows in set (0.31 sec)

如今假設您想知道公司中薪資最高的 10 位員工。清單 22 展現了另外一個返回此信息的子選擇。

清單 22. 使用子選擇查找薪資最高的員工

MariaDB [employees]> SELECT e.emp_no, e.last_name, e.first_name, 
     (
     SELECT MAX(salary) FROM salaries s
     WHERE e.emp_no = s.emp_no
     ) max_sal
     FROM employees e ORDER BY max_sal desc limit 10;
+--------+-----------+------------+---------+
| emp_no | last_name | first_name | max_sal |
+--------+-----------+------------+---------+
|  43624 | Pesch     | Tokuyasu   |  158220 |
| 254466 | Mukaidono | Honesty    |  156286 |
|  47978 | Whitcomb  | Xiahua     |  155709 |
| 253939 | Luders    | Sanjai     |  155513 |
| 109334 | Alameldin | Tsutomu    |  155377 |
|  80823 | Baca      | Willard    |  154459 |
| 493158 | Meriste   | Lidong     |  154376 |
| 205000 | Griswold  | Charmane   |  153715 |
| 266526 | Chenoweth | Weijing    |  152710 |
| 237542 | Hatcliff  | Weicheng   |  152687 |
+--------+-----------+------------+---------+
10 rows in set (2.66 sec)

我提到過您有時可使用 JOIN 完成子選擇的工做。清單 23 展現瞭如何使用 JOIN 查找薪資最高的 10 位員工。您能夠注意到,此查詢的執行速度比 清單 22 的子選擇更快。通常而言,若是注重性能,首先應該選擇使用聯接而不是子選擇。性能差別取決於您的數據庫引擎。

清單 23. 使用 JOIN 查找薪資最高的員工

MariaDB [employees]> SELECT e.emp_no, e.last_name, e.first_name,  max(s.salary) as max_sal 
     FROM employees e JOIN salaries s
     ON e.emp_no = s.emp_no
     GROUP BY e.emp_no ORDER BY max_sal desc limit 10;
+--------+-----------+------------+---------+
| emp_no | last_name | first_name | max_sal |
+--------+-----------+------------+---------+
|  43624 | Pesch     | Tokuyasu   |  158220 |
| 254466 | Mukaidono | Honesty    |  156286 |
|  47978 | Whitcomb  | Xiahua     |  155709 |
| 253939 | Luders    | Sanjai     |  155513 |
| 109334 | Alameldin | Tsutomu    |  155377 |
|  80823 | Baca      | Willard    |  154459 |
| 493158 | Meriste   | Lidong     |  154376 |
| 205000 | Griswold  | Charmane   |  153715 |
| 266526 | Chenoweth | Weijing    |  152710 |
| 237542 | Hatcliff  | Weicheng   |  152687 |
+--------+-----------+------------+---------+
10 rows in set (2.16 sec)

包含 ENUM 值的有趣結果

在 「瞭解表和列」 部分,我提到過 SQL 中的枚舉類型存在一些爭議。employees 表中的 gender 列是一個包含值 M 和 F 的 ENUM。這些值看起來像字符,但實際上它們在內部被存儲爲整數。它們依據其內部數值表示而存儲在一個 ORDER BY 子句中,這可能帶來使人驚訝的結果。清單 24 展現了按性別排序的前 5 位員工。

清單 24. 經過 ENUM 字段排序輸出

MariaDB [employees]> SELECT * FROM (
     SELECT * FROM employees LIMIT 5
     ) x ORDER BY x.gender;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date  |
+--------+------------+------------+-----------+--------+------------+
|  10001 | 1953-09-02 | Georgi     | Facello   | M      | 1986-06-26 |
|  10003 | 1959-12-03 | Parto      | Bamford   | M      | 1986-08-28 |
|  10004 | 1954-05-01 | Chirstian  | Koblick   | M      | 1986-12-01 |
|  10005 | 1955-01-21 | Kyoichi    | Maliniak  | M      | 1989-09-12 |
|  10002 | 1964-06-02 | Bezalel    | Simmel    | F      | 1985-11-21 |
+--------+------------+------------+-----------+--------+------------+
5 rows in set (0.00 sec)

您可能會奇怪地看到 M 值在 F 值以前列出。若是想按字母順序進行排列,可在 ORDERBY 子句中使用 CAST 或 CONVERT。例如:

ORDER BY CAST(x.gender AS CHAR)

建立、更改和刪除數據和表

您已經學習了表和如何瞭解它們的結構。您還學習瞭如何建立 SQL 查詢,以便從一個或多個表中的數據中尋找答案。在本教程的剩餘部分中,我將展現如何建立和操做表,如何插入、更新和刪除表中的數據。

建立表

假設您決定爲員工性別建立一個參考表,而不是使用枚舉。您決定提取性別的首字母,也就是英文字母 M 或 F。您還想要包含完整單詞 MALE 或 FEMALE 的另外一列。第一步是使用 CREATE TABLE 建立該表。CREATE TABLE 的基本形式提供了一個表名稱,後跟一個列、索引和約束列表。清單 25 展現瞭如何建立包含兩個列的 gender 表,一個列是表示主鍵的字符,另外一個列是一個最多 20 個字符的可變字符字段。

清單 25. 建立新表

MariaDB [employees]> CREATE TABLE gender (
     code CHAR(1) NOT NULL,
     gender VARCHAR(20) NOT NULL,
     PRIMARY KEY (code)
     );
Query OK, 0 rows affected (0.23 sec)

MariaDB [employees]> describe gender;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| code   | char(1)     | NO   | PRI | NULL    |       |
| gender | varchar(20) | NO   |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

插入、更新和刪除數據

如今您有一個空表,您須要在其中填入數據。使用 INSERT 命令加載一行或多行數據。您指定想要在其中插入數據的列的列表,而後指定一個或多個匹配值列表。清單 26 展現瞭如何添加您計劃的兩行。

清單 26. 在 gender 表中插入數據

MariaDB [employees]> INSERT INTO gender (code, gender)
     VALUES
     ('F', 'FEMALE'),
     ('M', 'MALE');
Query OK, 2 rows affected (0.03 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [employees]> select * from gender;
+------+--------+
| code | gender |
+------+--------+
| F    | FEMALE |
| M    | MALE   |
+------+--------+
2 rows in set (0.00 sec)

接下來假設您認爲一些員工可能須要在您知道其性別以前添加到數據庫中,因此您決定爲 UNASSIGNED 性別添加第三種可能性。清單 27 展現了另外一種插入數據的方式:經過使用 SET 子句。

清單 27. 在 gender 表中插入一個新行

MariaDB [employees]> INSERT INTO gender SET code='U', gender='UNSIGNED';
Query OK, 1 row affected (0.04 sec)

MariaDB [employees]> select * from gender;
+------+----------+
| code | gender   |
+------+----------+
| F    | FEMALE   |
| M    | MALE     |
| U    | UNSIGNED |
+------+----------+
3 rows in set (0.00 sec)

我使用的示例數據庫只有兩個 gender 值。假設您的公司採用了一種性別多樣性策略,您須要爲具備多樣性性別的員工提供額外的值。使用 VALUES 選項或 SET 選項和 INSERT INTO 向您的表中插入更多行。
因爲錄入錯誤,我原本打算插入 UNASSIGNED,但插入了 UNSIGNED。使用 UPDATE 命令修復此錯誤,如 清單 28 所示。

清單 28. 更新一個表值

MariaDB [employees]> UPDATE gender SET gender='UNASSIGNED' WHERE code='U';
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MariaDB [employees]> select * from gender;
+------+------------+
| code | gender     |
+------+------------+
| F    | FEMALE     |
| M    | MALE       |
| U    | UNASSIGNED |
+------+------------+
3 rows in set (0.00 sec)

如今人力資源經理告訴您,該公司始終在將新員工添加到數據庫以前就知道該員工的性別,因此您須要刪除表示未分配性別的條目。使用 DELETE 命令,如 清單 29 所示。

清單 29. 刪除一個錶行

MariaDB [employees]> DELETE FROM gender WHERE code='U';
Query OK, 1 row affected (0.04 sec)

MariaDB [employees]> select * from gender;
+------+--------+
| code | gender |
+------+--------+
| F    | FEMALE |
| M    | MALE   |
+------+--------+
2 rows in set (0.00 sec)

修改表

有時您但願更改一個表。您能夠執行的部分操做包括:

重命名一列。
添加一個新列。
刪除一列。
更改一列的數據類型。
更改一列上的約束。

清單 30 展現瞭如何修改 gender 表來添加一個新列 gender_fr,表示 gender 列的法語版本,加載新的法語數據,而後將現有的 gender 列重命名爲 gender_en。

清單 30. 修改 gender 表

MariaDB [employees]> ALTER TABLE gender ADD COLUMN gender_fr VARCHAR(20) AFTER gender;
Query OK, 0 rows affected (0.38 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [employees]> UPDATE gender SET gender_fr='MASCULIN' WHERE code='M';
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MariaDB [employees]> UPDATE gender SET gender_fr='FÉMININ' WHERE code='F';
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MariaDB [employees]> ALTER TABLE gender CHANGE COLUMN gender gender_en VARCHAR(20);
Query OK, 0 rows affected (0.38 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [employees]> select * from gender;
+------+-----------+-----------+
| code | gender_en | gender_fr |
+------+-----------+-----------+
| F    | FEMALE    | FÉMININ   |
| M    | MALE      | MASCULIN  |
+------+-----------+-----------+
2 rows in set (0.00 sec)

建立表和視圖的其餘方式

您還能夠建立一個表並填入來自一個 SELECT 的數據。清單 31 展現了一個建立女性員工表的簡單示例。

清單 31. 建立一個女性員工表

MariaDB [employees]> create table female_employees 
     select * from employees where gender='F';
Query OK, 120051 rows affected (3.22 sec)
Records: 120051  Duplicates: 0  Warnings: 0

當您以這種方式建立表時,新表可能未繼承來源表的全部屬性。比較 清單 32 中的表描述。您能夠注意到,female_employees 表沒有鍵。

清單 32. 比較 employees 和 female_employees 表

MariaDB [employees]> describe employees;
+------------+---------------+------+-----+---------+-------+
| Field      | Type          | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| emp_no     | int(11)       | NO   | PRI | NULL    |       |
| birth_date | date          | NO   |     | NULL    |       |
| first_name | varchar(14)   | NO   |     | NULL    |       |
| last_name  | varchar(16)   | NO   |     | NULL    |       |
| gender     | enum('M','F') | NO   |     | NULL    |       |
| hire_date  | date          | NO   |     | NULL    |       |
+------------+---------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

MariaDB [employees]> describe female_employees;
+------------+---------------+------+-----+---------+-------+
| Field      | Type          | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| emp_no     | int(11)       | NO   |     | NULL    |       |
| birth_date | date          | NO   |     | NULL    |       |
| first_name | varchar(14)   | NO   |     | NULL    |       |
| last_name  | varchar(16)   | NO   |     | NULL    |       |
| gender     | enum('M','F') | NO   |     | NULL    |       |
| hire_date  | date          | NO   |     | NULL    |       |
+------------+---------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

若是您使用現有數據來建立表,還須要考慮如何計劃將來將該數據保存在兩個同步的表中。在這個示例中,您可能想要一個 VIEW,它使您可以像表同樣使用 SELECT 的結果。數據保留在一個或多個基礎表中,並且僅須要更新一個副本。清單 33 展現瞭如何建立男性員工的視圖。請注意視圖名稱與 SELECT 之間的單詞 AS。

清單 33. 建立男性員工的視圖

MariaDB [employees]> CREATE VIEW male_employees AS
     select * from employees where gender='M';
Query OK, 0 rows affected (0.05 sec)

MariaDB [employees]> select * from male_employees limit 5;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date  |
+--------+------------+------------+-----------+--------+------------+
|  10001 | 1953-09-02 | Georgi     | Facello   | M      | 1986-06-26 |
|  10003 | 1959-12-03 | Parto      | Bamford   | M      | 1986-08-28 |
|  10004 | 1954-05-01 | Chirstian  | Koblick   | M      | 1986-12-01 |
|  10005 | 1955-01-21 | Kyoichi    | Maliniak  | M      | 1989-09-12 |
|  10008 | 1958-02-19 | Saniya     | Kalloufi  | M      | 1994-09-15 |
+--------+------------+------------+-----------+--------+------------+
5 rows in set (0.00 sec)

若是您想知道數據庫中的哪些表是真正的視圖,一個命令能夠幫助您。不一樣的數據庫使用不一樣的命令。在 MariaDB 中,使用:

show full tables

建立表時,您能夠組合您的列規範和 SELECT 的結果。做爲最後一個建立表的示例, 清單 34 展現了建立一種包含使用 CHAR(1) 字段而不是枚舉值來表 gender 的 employees 表的副本的方式,以及如何使用 IF 語句設置此值。

清單 34. 建立 employees 表的一個修訂的副本

MariaDB [employees]> CREATE TABLE employees_new (
     emp_no int(11) NOT NULL,
     birth_date date NOT NULL,
     first_name varchar(14) NOT NULL,
     last_name varchar(16) NOT NULL,
     gender CHAR(1),
     hire_date date NOT NULL,
     PRIMARY KEY (emp_no)
     ) select
     emp_no, birth_date, first_name, last_name,
     IF(gender = 'M', 'M', 'F') as gender,
     hire_date from employees;

Query OK, 300024 rows affected (5.92 sec)
Records: 300024  Duplicates: 0  Warnings: 0

MariaDB [employees]> describe employees_new;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| emp_no     | int(11)     | NO   | PRI | NULL    |       |
| birth_date | date        | NO   |     | NULL    |       |
| first_name | varchar(14) | NO   |     | NULL    |       |
| last_name  | varchar(16) | NO   |     | NULL    |       |
| gender     | char(1)     | YES  |     | NULL    |       |
| hire_date  | date        | NO   |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

外鍵的建立和維護不屬於這篇介紹性教程的討論範圍。可是,您仍然可使用 JOIN 聯接 employees_new 和 gender 表來執行查詢,好比我在 清單 35 中演示的查詢。

清單 35. 聯接 employees_new 和 gender

MariaDB [employees]> select e.emp_no, e.first_name, e.last_name, e.gender,
     g.gender_en, g.gender_fr 
     from employees_new e join gender g on e.gender=g.code
     limit 5;
+--------+------------+-----------+--------+-----------+-----------+
| emp_no | first_name | last_name | gender | gender_en | gender_fr |
+--------+------------+-----------+--------+-----------+-----------+
|  10001 | Georgi     | Facello   | M      | MALE      | MASCULIN  |
|  10002 | Bezalel    | Simmel    | F      | FEMALE    | FÉMININ   |
|  10003 | Parto      | Bamford   | M      | MALE      | MASCULIN  |
|  10004 | Chirstian  | Koblick   | M      | MALE      | MASCULIN  |
|  10005 | Kyoichi    | Maliniak  | M      | MALE      | MASCULIN  |
+--------+------------+-----------+--------+-----------+-----------+
5 rows in set (0.00 sec)

刪除表和數據庫

我展現瞭如何使用 DELETE 從表中刪除行。若是您想要刪除一列而不是一行,則須要使用 ALTER TABLE。例如,若是您但願從 female_employees 表刪除 gender 列,可使用 清單 36 中演示的命令。

清單 36. 從 female_employees 表刪除 gender 列

MariaDB [employees]> ALTER TABLE female_employees DROP COLUMN gender;
Query OK, 0 rows affected (4.32 sec)                
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [employees]> describe female_employees;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| emp_no     | int(11)     | NO   |     | NULL    |       |
| birth_date | date        | NO   |     | NULL    |       |
| first_name | varchar(14) | NO   |     | NULL    |       |
| last_name  | varchar(16) | NO   |     | NULL    |       |
| hire_date  | date        | NO   |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

要丟棄 female_employees 表和 male_employees 視圖,可使用 DROP TABLE 和 DROP VIEW 命令,如 清單 37 所示。

清單 37. 刪除 female_employees 表和 male_employees 視圖

MariaDB [employees]> drop table female_employees;
Query OK, 0 rows affected (0.14 sec)

MariaDB [employees]> drop view male_employees;
Query OK, 0 rows affected (0.00 sec)

若是您想刪除整個 employees 數據庫和它的全部表,可使用 DROP DATABASE 命令,如 清單 38 所示。

清單 38. 刪除整個 employees 數據庫

MariaDB [employees]> drop database employees;
Query OK, 10 rows affected (0.92 sec)

對 SQL 的簡要介紹到此就結束了。我只簡單介紹了一個大型項目的不多的一部分,您可使用本教程做爲起點來進一步探索。

免費提供最新Linux技術教程書籍,爲開源技術愛好者努力作得更多更好:http://www.linuxprobe.com/

相關文章
相關標籤/搜索