《SQL 必知必會》- 閱讀索引

閱讀總結

用于了解 SQL 的基礎知識還是非常好的。

在使用時可以具體看 DBMS 文檔。

以下 SQL 以 cnpmjs.org 數(shù)據(jù)庫為例。


[toc]


第 1 課 了解 SQL

1.1 數(shù)據(jù)庫基礎

1.1.1 數(shù)據(jù)庫

  • 數(shù)據(jù)庫(database):保存有組織的數(shù)據(jù)的容器(通常是一個文件或一組文件)
  • DBMS,數(shù)據(jù)庫管理系統(tǒng)(即數(shù)據(jù)庫軟件)

1.1.2 表

  • 表(table):某種特定類型數(shù)據(jù)的結構化清單(一種結構化的文件)
    • 統(tǒng)一類型的數(shù)據(jù)
    • 表名在數(shù)據(jù)庫中唯一
  • 模式(schema):關于數(shù)據(jù)庫和表的布局及特性的信息

1.1.3 列

  • 列(column):表中的一個字段
  • 數(shù)據(jù)類型(datatype):所允許的數(shù)據(jù)的類型,每個表列都有相應的數(shù)據(jù)類型,它限制(或允許)該列中存儲的數(shù)據(jù)
    • 幫助分類數(shù)據(jù)
    • 優(yōu)化磁盤使用
    • 數(shù)據(jù)類型兼容問題(不同的 DBMS)

1.1.3 行

  • 行(row):表中的一個記錄(record)

1.1.5 主鍵

  • 主鍵(primary key):一列(或一組列),其值能夠唯一標識表中的每一行
    • 任何滿足條件的列都可以作為主鍵
      • 唯一標識行
      • 不允許 NULL
      • 不允許修改或更新
      • 刪除后其值不能重用
    • 不是必須,也可以是多列主鍵

1.2 什么是 SQL

  • SQL:結構化查詢語言(Structured Query Language)
    • 不是某個 DBMS 專用的
    • 簡單易學,強描述性
    • 強大
  • SQL 的擴展:針對特定 DBMS 的簡化特定操作執(zhí)行的方法
  • 標準 SQL 由 ANSI 標準委員會管理

1.3 動手實踐

1.4 小結

  • 什么是 SQL
  • 為什么很有用
  • 基本的數(shù)據(jù)庫術語

第 2 課 檢索數(shù)據(jù)

2.1 SELECT 語句

  • 關鍵詞(keyword):作為 SQL 組成部分的保留字,不能用作表或列的名字
  • SELECT 語句:從一個或多個表中檢索信息
    • 想選擇什么,以及從什么地方選擇

2.2 檢索單個列

SELECT name FROM USER
  • 數(shù)據(jù)未排序(可能是被添加到表中的屬性,可能不是)
  • 多條 SQL 必須以 ; 分隔
  • SQL 語句不區(qū)分大小寫
  • 所有空格都被忽略

2.3 檢索多個列

SELECT id, name FROM user
  • 列名之間 , 分隔

2.4 檢索所有列

SELECT * FROM user
  • 使用通配符 *
    • 耗費性能
    • 可以檢索未知列

2.5 檢索不同的值

SELECT DISTINCT name FROM module
  • 使用 DISTINCT 關鍵字
    • 必須直接放在列名前
    • 作用于所有的列

2.6 限制結果

# MySQL、MariaDB、PostgreSQL、SQLite
SELECT name from user LIMIT 10

# 第 5 行后的 10 行
SELECT name from user LIMIT 10 OFFSET 5
  • 不同的 DBMS 不同
  • LIMIT、OFFSET

2.7 使用注釋

SELECT name FROM user -- 注釋
# 注釋
/*
 * 注釋
 */
  • -- 行內
  • # 單行
  • /* */ 多行

2.8 小結

  • SELECT 語句檢索
  • 注釋

第 3 課 排序檢索數(shù)據(jù)

3.1 排序數(shù)據(jù)

SELECT name from user ORDER BY name
SELECT name from user ORDER BY id
  • 關系數(shù)據(jù)庫設計理論認為:如果不明確規(guī)定排序順序,則不應該假定檢索出的數(shù)據(jù)的順序有任何意義
  • 子句(clause):SQL 語句由子句構成,一個子句通常由一個關鍵字加所提供的數(shù)據(jù)組成
  • ORDER BY
    • ORDER BY 子句要求在 SELECT 語句的最后一句
    • 可以通過非檢索列排序

3.2 按多個列排序

SELECT id, name, email from user ORDER BY name, id
  • 按優(yōu)先級以逗號分隔

3.3 按列位置排序

SELECT id, name, email from user ORDER BY 2, 3
# =
SELECT id, name, email from user ORDER BY name, email
  • 用所選列的序號代替重復列名
  • 不建議使用

3.4 指定排序方向

# 先按 name 降序,再按 email 升序
SELECT id, name, email from user ORDER BY name DESC, email
  • 使用 DESC 關鍵字
    • 只應用于直接位于前面的列名

3.5 小結

  • ORDER BY 子句

第 4 課 過濾數(shù)據(jù)

4.1 使用 WHERE 子句

SELECT * from user WHERE name = 'xiaoming'
  • WHERE 指定搜索條件(過濾條件)
    • WHERE 子句放在表名(FROM 子句)后
  • 使用 SQL 過濾而不是應用過濾

4.2 WHERE 子句操作符

  • 操作符(不同 DBMS 不同)
操作符 說明
=
<> 不等于
!= 不等于
<
<=
>
>=
BETWEEN ... AND ...
IS NULL

4.2.1 檢查單個值

SELECT * from user WHERE id < 10

4.2.2 不匹配檢查

SELECT * from user WHERE npm_user <> 1
  • 有的 DBMS 不支持 !=

4.2.3 范圍值檢查

SELECT * from user WHERE id BETWEEN 10 AND 100

4.2.3 空值檢查

SELECT * from user WHERE email IS NULL
  • IS NULL 子句
  • NULL,無值

4.3 小結

  • WHERE 子句過濾

第 5 課 高級數(shù)據(jù)過濾

5.1 組合 WHERE 子句

  • 操作符(operator,邏輯操作符):用來聯(lián)結或改變 WHERE 子句中的子句的關鍵字

5.1.1 AND 操作符

SELECT *
FROM user
WHERE npm_user = 1 AND email IS NULL
  • AND:用在 WHERE 子句中的關鍵字,用來表示檢索滿足所有給定條件的行

5.1.2 OR 操作符

  • OR:用在 WHERE 子句中的關鍵字,用來表示檢索匹配任一給定條件的行

5.1.3 求值順序

# npm_user = 0 或 1,同時 email 為空值
SELECT *
FROM user
WHERE (npm_user = 1 OR npm_user = 0) AND email IS NULL
  • SQL 會優(yōu)先處理 AND 操作符
  • 使用 () 來控制優(yōu)先級
  • 建議 AND OR 混用時始終使用圓括號

5.2 IN 操作符

SELECT * 
FROM module
WHERE authoer IN ('xiaoming', 'xiaohong')
ORDER BY name
  • IN:WHERE 子句中用來指定要匹配值的清單的關鍵字,功能與 OR 相當
    • 多選項時更直觀
    • 與 AND/OR 組合時,求值順序更易管理
    • 比一組 OR 執(zhí)行更快
    • 最大優(yōu)點是可以包含其他 SELECT 語句,能更動態(tài)地建立 WHERE 子句

5.3 NOT 操作符

SELECT *
FROM user
WHERE NOT (npm_user = 1 AND id > 10)
  • NOT:WHERE 子句中用來否定其后條件的關鍵字

5.4 小結

  • AND/OR
  • 求值順序
  • NOT

第 6 課 用通配符進行過濾

6.1 LIKE 操作符

  • 通配符(wildcard):用來匹配值的一部分的特殊字符
    • 只能用于字符串
  • 搜索模式(search pattern):由字面值、通配符或兩者組合構成的搜索條件
  • 謂詞(predicate):LIKE 作為謂詞

6.1.1 百分號(%)通配符

# xiao 開頭的 name
SELECT * 
FROM user
WHERE name LIKE 'xiao%'
  • %:任何字符出現(xiàn)任意次數(shù)
    • 可以在搜索模式的不同位置:a%e
  • 根據(jù) DBMS 的不同及其配置,可以區(qū)分大小寫
  • 不匹配 NULL

6.1.2 下劃線(_)通配符

# 兩個字符的 163 郵箱
SELECT * 
FROM user
WHERE email LIKE '__@163.com'
  • _:匹配單個字符

6.1.3 方括號([])通配符

# 非 a 和 b 開頭的 name
SELECT *
FROM user
WHERE name LIKE '[^ab]%'
  • []: 指定字符集,必須匹配指定位置的一個字符
    • 只有 Access 和 SQL Server 支持集合
  • ^:否定集合

6.2 使用通配符的技巧

  • 不過度使用,通配符是最后的手段
  • 不要用在搜索模式的開始處,否則會很慢
  • 注意通配符的位置,容易出錯

6.3 小結

  • 什么是通配符
  • 如何在 WHERE 子句中使用
  • 注意點

第 7 課 創(chuàng)建計算字段

7.1 計算字段

  • 字段(field):與列基本相同,經(jīng)?;Q使用
  • 只有數(shù)據(jù)庫知道 SELECT 語句中哪些是實際的表列,哪些是計算字段,對應用程序是透明的
  • 把數(shù)據(jù)轉換和格式化工作放在數(shù)據(jù)庫中會比在應用程序中更快

7.2 拼接字段

SELECT CONCAT(name, '[', email, ']') AS info
FROM user
WHERE id < 100
  • CONCAT
  • TRIM、LTRIM(清除左邊的空格)、RTRIM(清除右邊的空格)
  • AS:別名或導出列
    • 使用 AS 是最佳實踐
    • 讓應用程序可以按名稱引用這個列
    • 可以對列中的不合法字符重新命名
    • 增加可讀性

7.3 執(zhí)行算術計算

SELECT dist_size / 1024 AS dist_kb
FROM module
LIMIT 100
  • SELECT 可以用來測試計算(省略 FROM),如 SELECT 3 * 2 返回 6

7.4 小結

  • 計算字段及如何創(chuàng)建
  • 字符串拼接
  • 算數(shù)計算
  • 別名

第 8 課 使用函數(shù)處理數(shù)據(jù)

8.1 函數(shù)

  • 提供數(shù)據(jù)的轉化和處理方法
  • 各 DBMS 差異大,因此使用函數(shù)的 SQL 可移植性差

8.2 使用函數(shù)

  • 處理文本字符串
  • 數(shù)值算數(shù)操作
  • 處理日期和時間
  • 返回 DBMS 證使用的特殊信息(如用戶登錄信息)的系統(tǒng)函數(shù)

8.2.1 文本處理函數(shù)

SELECT UPPER(name) AS name_upcase, email
From user
  • 常用的文本處理函數(shù)
函數(shù) 說明
LEFT 返回字符串左邊的字符
LENGTH 返回字符串長度
LOWER 返回字符串小寫
UPPER 返回字符串大寫
LTRIM 去字符串左邊空格
RIGHT 返回字符串右邊的字符
RTRIM 去字符串右邊空格
SOUNDEX 返回字符串的 SOUNDEX 值(語音描述)

8.2.2 日期和時間處理函數(shù)

  • DBMS 都有自己的日期時間形式和處理函數(shù)
    • 高效排序或過濾
    • 節(jié)省存儲空間
    • 可移植性差

8.2.3 數(shù)值處理函數(shù)

  • 常用數(shù)值處理函數(shù)
函數(shù) 說明
ABS 絕對值
COS 余弦值
EXP 指數(shù)值
PI 圓周率
SIN 正弦值
SQRT 平方根
TAN 正切

8.3 小結

  • 有用
  • 各 DBMS 不一致

第 9 課 匯總數(shù)據(jù)

9.1 聚集函數(shù)

  • 只需要匯總數(shù)據(jù)而不需要實際檢索,如
    • 滿足某個條件的行的行數(shù)
    • 某些行的和
    • 某些列的最大值、平均值等
  • 聚集函數(shù)(aggregate function):對某些行運行的函數(shù),計算并返回一個值
  • 在各 DMBS 中實現(xiàn)相當一致
函數(shù) 說明
AVG 某列的平均值
COUNT 某列的行數(shù)
MAX 某列的最大值
MIN 某列的最小值
SUM 某列之和

9.1.1 AVG() 函數(shù)

SELECT AVG(dist_size) 
AS avg_dist_size 
FROM module

SELECT AVG(dist_size)
AS avg_babel_dist_size
FROM module
WHERE name LIKE '@babel/%'
  • 只能用于單列,多個列的平均值必須使用多個 AVG()
  • 對 NULL
    • 值為 NULL 的行會被忽略

9.1.1 COUNT() 函數(shù)

SELECT COUNT(*) AS user_count FROM user;
SELECT COUNT(email) AS user_with_email_count FROM user;
  • 對 NULL
    • COUNT(*) 對表中行的數(shù)目進行技術,不管列中是否包含 NULL
    • COUNT(column) 對特定列中非 NULL 值的行的數(shù)目進行計數(shù)

9.1.3 MAX() 函數(shù)

SELECT MAX(dist_size) AS max_dist_size FROM module
  • 對非數(shù)值
    • 返回按該列排序后的最后一行
  • 對 NULL
    • 值為 NULL 的行會被忽略

9.1.4 MIN() 函數(shù)

  • 與 MAX 相反

9.1.5 SUM() 函數(shù)

SELECT SUM(dist_size) AS total_dist_size FROM module
SELECT SUM(dist_size*LENGTH(name)) AS for_test FROM module
  • 對非數(shù)值忽略
  • 對 NULL 忽略

9.2 聚集不同的值

SELECT AVG(DISTINCT dist_size) 
AS avg_dist_size 
FROM module
  • 默認為 ALL,對所有行執(zhí)行計算
  • 指定 DISTINCT 只包含不同的值

9.3 組合聚集函數(shù)

SELECT 
MAX(dist_size) AS max_dist_size,
MIN(dist_size) AS min_dist_size,
FROM module

9.4 小結

  • 使用 5 個聚集函數(shù)來匯總數(shù)據(jù)

第 10 課 分組數(shù)據(jù)

10.1 數(shù)據(jù)分組

  • 使用分組可以將數(shù)據(jù)分成多個邏輯組,對每個組進行聚集計算

10.2 創(chuàng)建分組

# 每個包及其版本數(shù)
SELECT name, COUNT(*) AS version_count 
FROM module 
GROUP BY name
  • GROUP BY 子句可以包含任意數(shù)目的列
  • 列可以是檢索列或有效表達式(不能是聚集函數(shù))
  • NULL 會被作為一個分組返回
  • 放在 WHERE 后,ORDER BY 前

10.3 過濾分組

# 版本數(shù)大于 100 的包及其版本數(shù)
SELECT name, COUNT(*) AS version_count 
FROM module 
GROUP BY name 
HAVING COUNT(*) >= 100
# 體積大于 1024 的版本數(shù)大于 100 的包及其版本
SELECT name, COUNT(*) AS version_count 
FROM module 
WHERE dist_size > 1024
GROUP BY name 
HAVING COUNT(*) >= 100
  • HAVING 語法同 WHERE,其能代替 WHERE
  • HAVING 過濾分組,WHERE 過濾行
  • HAVING 在數(shù)據(jù)分組后進行過濾,WHERE 在分組前進行過濾

10.4 分組和排序

  • ORDER BY 和 GROUP BY
ORDER BY GROUP BY
對產生的輸出排序 對行分組,輸出不一定是分組的順序
任意列都可以使用 只能使用選擇列或表達式列
不一定需要 在與聚集函數(shù)一起使用時必要

10.5 SELECT 子句順序

  1. SELECT
  2. FROM
  3. WHERE
  4. GROUP BY
  5. HAVING
  6. ORDER BY

10.6 小結

  • 使用 GROUP BY 對多組數(shù)據(jù)匯總計算
  • HAVING 以及和 WHERE 的區(qū)別

第 11 課 使用子查詢

11.1 子查詢

  • 查詢(query):任何 SQL 語句都是查詢,但一般指 SELECT 語句
  • 子查詢(subquery):嵌套在其他查詢中查詢

11.2 利用子查詢進行過濾

# 內部作者的包
SELECT DISTINCT name
FROM module
WHERE author IN (
    SELECT name 
    FROM user 
    WHERE npm_user = 0
)
  • 子查詢的 SELECT 語句只能查詢單個列
  • 子查詢存在性能問題,更有效方法見 12 章

11.3 作為計算字段使用子查詢

# 每個有包的作者的包的數(shù)量
SELECT name, (
    SELECT COUNT(DISTINCT name) 
    FROM module
    WHERE module.author = user.name
) AS module_count
FROM user
HAVING module_count > 0
  • 通過 table.column 來完全限定列名,避免歧義
  • JOIN 是更好的解決方案

11.4 小結

  • 子查詢及如何使用

第 12 課 聯(lián)結表

12.1 聯(lián)結

  • JOIN

12.1.1 關系表

  • 將數(shù)據(jù)分層多個關聯(lián)的表

12.1.2 為什么使用聯(lián)結

  • 聯(lián)結是一種機制,用來在一條 SELECT 語句中關聯(lián)表

12.2 創(chuàng)建聯(lián)結

SELECT module.name, version, user.name, email
FROM module, user
WHERE module.author = user.name

12.2.1 WHERE 子句的重要性

  • 沒有 WHERE,檢索的結果是笛卡爾積(第一張表的行數(shù)乘以第二張表的行數(shù)),也叫做叉聯(lián)結

12.2.2 內聯(lián)結

  • 上面的例子是等值聯(lián)結,也稱為內聯(lián)結
  • 可以用 INNER JOIN 語法
SELECT module.name, version, user.name, email
FROM module INNER JOIN user
ON module.author = user.name

12.2.3 聯(lián)結多個表

  • 同兩張表
  • 過多的聯(lián)結表耗費性能

12.3 小結

  • 聯(lián)結是 SQL 中最重要、最強大的特性
  • 要求對關系數(shù)據(jù)庫設計有基本的了解

第 13 課 創(chuàng)建高級聯(lián)結

13.1 使用表別名

SELECT m.name, version, u.name, email
FROM module AS m INNER JOIN user AS u
ON m.author = u.name

13.2 使用不同類型的聯(lián)結

  • 內聯(lián)結(等值聯(lián)結)
  • 自聯(lián)結(self join)
  • 自然聯(lián)結(natural join)
  • 外聯(lián)結(outer join)

13.2.1 自聯(lián)結

# 和 babel 同作者的包
SELECT DISTINCT m1.name, m1.author
FROM module AS m1, module AS m2
WHERE m1.author = m2.author AND m2.name = 'babel'
  • 用來替代從相同表中檢索數(shù)據(jù)的使用子查詢的語句
  • 通常 DBMS 處理聯(lián)結遠比子查詢快

13.2.2 自然聯(lián)結

  • 聯(lián)結中至少有一列會出現(xiàn)在多個表中,自然聯(lián)結使每一列只返回一次
  • 以上的內聯(lián)結都是自然聯(lián)結

13.3.3 外聯(lián)結

# 作者及其包
SELECT DISTINCT u.name, u.email, m.name
FROM user AS u LEFT OUTER JOIN module AS m
ON u.name = m.author
  • 需要包含沒有關聯(lián)行的那些行的聯(lián)結
  • LEFT OUTER JOIN、RIGHT OUTER JOIN、FULL OUTER JOIN(mysql 等不支持)

13.3 使用帶聚集函數(shù)的聯(lián)結

# 所有沒有發(fā)過包的用戶
SELECT u.name, u.email, COUNT(DISTINCT m.name) AS module_count
FROM user AS u LEFT OUTER JOIN module AS m
ON u.name = m.author
GROUP BY u.name
HAVING module_count < 1

13.4 使用聯(lián)結和聯(lián)結條件

  • 注意使用的聯(lián)結類型,應使用內聯(lián)結還是外聯(lián)結
  • 注意各 DBMS 的聯(lián)結語法
  • 使用正確的聯(lián)結條件
  • 多表聯(lián)結合法且有用,注意使用前分開測試

13.5 小結

  • 聯(lián)結類型
  • 聯(lián)結中聚集
  • 注意事項

第 14 課 組合查詢

14.1 組合查詢

  • 并(union):執(zhí)行多個查詢(多條 SELECT 語句)并將結果作為一個查詢結果集返回,也稱為復合查詢
  • 使用場景
    • 在一個查詢中從不同的表返回結構數(shù)據(jù)
    • 對一個表執(zhí)行多個查詢,按一個查詢返回結果
  • 具有多個 WHERE 子句的 SELECT 語句都可以作為一個組合查詢

14.2 創(chuàng)建組合查詢

14.2.1 使用 UNION

SELECT name FROM user WHERE npm_user = 0
UNION
SELECT name FROM user WHERE email IS NULL
# 等于
SELECT name FROM user WHERE npm_user = 0 OR email IS NULL
  • 多數(shù) DBMS 會將 UNION 優(yōu)化為一條 SELECT 語句

14.2.2 UNION 規(guī)則

  • 必須由兩條及以上 SELECT 語句組成,語句之間用 UNION 分隔
  • 每個查詢必須包含相同的列、表達式或聚集函數(shù)
  • 列數(shù)據(jù)類型必須兼容

14.2.3 包含或取消重復的行

  • UNION 會過濾重復的行
  • UNION ALL 包含重復的行,這是 WHERE 無法完成的

14.2.4 對組合查詢結果排序

  • ORDER BY 放在所有 SELECT 之后

14.3 小結

  • UNION 組合查詢語句

第 15 課 插入數(shù)據(jù)

15.1 數(shù)據(jù)插入

  • 插入數(shù)據(jù)的方式
    • 完整的行
    • 行的一部分
    • 某些查詢的結果
  • DBMS 中的 INSERT 權限

15.1.1 插入完整的行

# 插入用戶,可省略 allow null 列或有默認值的列
INSERT INTO user
(name, email, npm_user)
VALUES
('1', '2', 0)

15.1.2 插入部分行

  • 如 15.1.1
  • 省略的列必須滿足條件之一
    • 允許為 NULL
    • 表定義中有默認值

15.1.3 插入檢索出的數(shù)據(jù)

# 從 user2 中檢索出 n 行數(shù)據(jù)插入 user
INSERT INTO user(name, email, npm_user)
SELECT name, email, npm_user FROM user2
  • SELECT 后的列的位置與 INSERT 對應,而無須列名一致

15.2 從一個表復制到另一個表

# 創(chuàng)建新表 user2,并復制 user 數(shù)據(jù)
SELECT * INTO user2 FROM user
# mysql、sqllite 等
CREATE TABLE user2 AS
SELECT * FROM user
  • 任何 SELECT 選項和子句都可以使用,包括 WHERE、GROUP BY
  • 可用聯(lián)結
  • 只能插入到一張表中

15.3 小結

  • 使用 INSERT 將行插入到數(shù)據(jù)庫表中

第 16 課 更新和刪除數(shù)據(jù)

16.1 更新數(shù)據(jù)

UPDATE user
SET email = NULL,
SET npm_user = 0
WHERE name = 'a'
  • UPDATE
    • 更新特定行,注意 WHERE
    • 更新所有行
  • DBMS 中的 UPDATE 權限
  • UPDATE 語句組成
    • 要更新的表
    • 列名和它們的新值
    • 行的過濾條件

16.2 刪除數(shù)據(jù)

DELETE FROM user
WHERE name = 'a'
  • DELETE
    • 刪除特定行,注意 WHERE
    • 刪除所有行
  • DBMS 中的 DELETE 權限
  • 刪除的是行而不是表
  • 使用 TRUNCATE TABLE 來刪除所有行更快(因為不記錄數(shù)據(jù)的變動)

16.3 更新和刪除的指導原則

  • 除非確實打算更新和刪除每一行,否則必須帶 WHERE
  • 保證每個表都有主鍵
  • 先用 SELECT 測試,保證正確
  • 使用強制實施引用完整性的數(shù)據(jù)庫
  • 如果 DBMS 支持,施加約束不允許執(zhí)行不帶 WHERE 的

16.4 小結

  • UPDATE、DELETE 的使用
  • 保證數(shù)據(jù)安全應該遵循的一些指導原則

第 17 課 創(chuàng)建和操縱表

17.1 創(chuàng)建表

  • 用交互式創(chuàng)建和管理表的工具
  • 用 SQL 語句創(chuàng)建

17.1.1 表創(chuàng)建基礎

CREATE TABLE test (
    a CHAR(10) NOT NULL,
    b VARCHAR(1000) NOT NULL,
    c BIGINT(10) NOT NULL
)

17.1.2 使用 NULL 值

# 允許 b 為 NULL
CREATE TABLE test (
    a CHAR(10) NOT NULL,
    b VARCHAR(1000),
    c BIGINT(10) NOT NULL
)
  • 每個表列要么是 NULL 列,要么是 NOT NULL 列
  • 允許 NULL 值的列不能作為主鍵
  • 有的 DBMS 需要指定關鍵詞 NULL

17.1.3 指定默認值

CREATE TABLE test (
    a CHAR(10) NOT NULL DEFAULT 1,
    b VARCHAR(1000),
    t DATE NOT NULL DEFAULT CURRENT_DATE()
)

17.2 更新表

ALTER TABLE test
ADD d CHAR(20);
ALTER TABLE test
DROP COLUMN a;
  • 對 ALTER TABLE 的限制
    • 盡量避免在表中包含數(shù)據(jù)時更新
    • 所有 DBMS 都支持增加列
    • 許多 DBMS 不允許刪除或更改列
    • 多少 DMBS 允許重命名列
    • 許多 DBMS 限制對有數(shù)據(jù)的列更改,對無數(shù)據(jù)的列幾乎沒有限制
  • 復雜的表結構更改一般需要手動刪除過程
    1. 用新的列布局創(chuàng)建一個新表
    2. 用 INSERT SELECT 從舊表復制數(shù)據(jù)倒新表
    3. 檢驗包含所需數(shù)據(jù)的新表
    4. 重命名舊表(可以刪除)
    5. 用舊表原來的名字重命名新表
    6. 重新創(chuàng)建觸發(fā)器、存儲過程、索引和外鍵

17.3 刪除表

DROP TABLE test;
  • 使用關系規(guī)則防止意外刪除,如果是某個關系的組成部分,DBMS 會阻止刪除

17.4 重命名表

  • 不同 DBMS 有差別,MySQL 用 RENAME

17.5 小結

  • CREATE TABLE
  • ALTER TABLE
  • DROP TABLE
  • RENAME TABLE

第 18 課 使用視圖

18.1 視圖

  • 視圖是虛擬的表,只包含使用時動態(tài)檢索數(shù)據(jù)的查詢
  • 可以用與表基本相同的方式使用
  • 本身不包含數(shù)據(jù)
  • 每次使用視圖時,都必須處理傳執(zhí)行時所需要的所有檢查,因此比較耗費性能

18.1.1 為什么使用視圖

  • 重用 SQL 語句
  • 簡化復制的 SQL 操作。在編寫查詢后,可以方便地重用它而不必知道基本查詢細節(jié)
  • 使用表的一部分而不是整個表
  • 保護數(shù)據(jù)。可以授予用戶訪問表的特定部分的權限
  • 更改數(shù)據(jù)格式和表示。視圖可返回與底層表的表示和格式不同的數(shù)據(jù)

18.1.2 視圖的規(guī)劃和限制

  • 視圖命名唯一
  • 不限制視圖數(shù)量
  • 創(chuàng)建視圖的權限
  • 視圖嵌套
  • 實體不能所有,也不能有關聯(lián)的觸發(fā)器或默認值
  • 其它參與具體的 DBMS 文檔

18.2 創(chuàng)建視圖

  • CREATE VIEW
  • DROP VIEW

18.2.1 利用視圖簡化復雜的聯(lián)結

CREATE VIEW user_module AS
SELECT user.name , user.email, module.name as module
FROM user INNER JOIN module
on user.name = module.author;

18.2.2 用視圖重新格式化檢索出的數(shù)據(jù)

18.2.3 用視圖過濾不想要的數(shù)據(jù)

18.2.4 使用視圖與計算字段

18.3 小結

  • 視圖為虛擬的表,包含的不是數(shù)據(jù)而是根據(jù)需要檢索數(shù)據(jù)的查詢

第 19 課 使用存儲的過程

19.1 存儲過程

  • 存儲過程是為以后使用而保存的一條或多條 SQL 語句??梢暈榕募ú粌H限于此)

19.2 為什么要使用存儲過程

  • 好處:簡單、安全、高性能
    • 把處理封裝在一個易用的單元,簡化復雜的操作
    • 使用同一存儲過程,可以保證數(shù)據(jù)的一致性
    • 隔離變動
    • 存儲過程通常以編譯過的形式存儲,簡化了 DBMS 處理工作,提高了性能
    • 可以使用一些職能用在單個請求中的 SQL 元素和特性
  • 缺陷
    • DBMS 語法差異,幾乎不可移植
    • 編寫存儲過程復雜
  • 編寫存儲過程權限

19.3 執(zhí)行存儲過程

  • EXECUTE + 存儲過程名 + 參數(shù)

19.4 創(chuàng)建存儲過程

19.5 小結

  • 見具體 DBMS

第 20 課 管理事務處理

20.1 事務處理

  • 事務處理(transaction processing):通過確保成批的 SQL 操作要么完全執(zhí)行,要么完全不執(zhí)行,來維護數(shù)據(jù)庫的完整性
  • 幾個術語
    • 事務(transaction):一組 SQL 語句
    • 回退(rollback):撤銷指定 SQL 語句的過程
    • 提交(commit):將未存儲的 SQL 語句結果寫入數(shù)據(jù)庫表
    • 保留點(savepoint):事務處理中設置的臨時占位符(placeholder),可以對它發(fā)布回退(與回退整個事務處理不同)
  • 可以回退:INSERT、UPDATE、DELETE 語句

20.2 控制事務處理

# MySQL
START TRANSACTION
# ...
  • 管理事務的關鍵在于將 SQL 語句組成分解為邏輯塊,并明確規(guī)定數(shù)據(jù)何時應該回退,何時不應該回退

20.2.1 使用 ROLLBACK

# 使用 ROLLBACK 撤銷
DELETE FROM test;
ROLLBACK;

20.2.2 使用 COMMIT

# SQL server
BEGIN TRANSACTION;
DELETE ...
COMMIT TRANSACTION;
  • 一般的 SQL 語句都是直接執(zhí)行和編寫的,即隱式提交(implicit commit),提交操作是自動進行的
  • 在事物處理中,提交通常通過 COMMIT 明確提交

20.2.3 使用保留點

SAVEPOINT delete1;
# DELTE ...
ROLLBACK TO delete1;
  • 保留點越多越好,以進行靈活地回退

20.3 小結

  • 事務是必須完整執(zhí)行的 SQL 語句塊
  • 使用 COMMIT 和 ROLLBACK 對寫數(shù)據(jù)、撤銷數(shù)據(jù)進行明確管理
  • 使用保留點控制回退操作
  • 參考具體 DBMS

第 21 課 使用游標

21.1 游標

  • 結果集(result set):SQL 查詢所檢索出的結果
  • 游標(cursor):一個存儲在 DBMS 服務器上的數(shù)據(jù)庫查詢,不是一條 SQL 語句,而是被該語句檢索出來的結果集。應用程序可以根據(jù)需要滾動或瀏覽其中的數(shù)據(jù)
  • 對于 WEB 應用用處不大,因為應用服務器是數(shù)據(jù)庫客戶端而不是最終用戶

21.2 使用游標

21.3 小結


第 22 課 高級 SQL 特性

22.1 約束

  • 約束(constraint):管理如何插入或處理數(shù)據(jù)庫數(shù)據(jù)的規(guī)則
  • DBMS 通過在數(shù)據(jù)庫表上引用完整性(referential integrity)

22.1.1 主鍵

  • 主鍵是一種特殊的約束,用來保證一列(或一組列)中的值是唯一的,且永不改動
  • 任意列只要滿足以下條件,都可以用于主鍵
    • 任意兩行的主鍵值都不相同
    • 列中不允許 NULL 值
    • 列從不修改或更新
    • 主鍵值不能重用
  • 定義主鍵:創(chuàng)建表時或 CONSTRAINT PRIMARY KEY
CREATE TABLE test (
    name CHAR(10) NOT NULL PRIMARY KEY;
);
ALTER TABLE test 
ADD CONSTRAINT PRIMARY KEY (name);

22.1.2 外鍵

  • 外鍵:表中的一列,其值必須列在另一表的主鍵中。是保證引用完整性的極其重要部分
  • 定義外鍵:REFERENCES、CONSTRAINT FOREIGN KEY
  • 可以防止意外刪除,DBMS 不允許刪除在另一個表中具有關聯(lián)行的行
CREATE TABLE module(
    author CHAR(20) NOT NULL REFERENCES user(name)
)
ALTER TABLE module
ADD CONSTRAINT FOREIGN KEY author REFERENCES user(name)

22.1.3 唯一約束

  • 唯一約束:用來保證一列(或一組列)中的數(shù)據(jù)是唯一的
  • 與主鍵的區(qū)別:
    • 表可以包含多個唯一約束
    • 唯一約束列可以包含 NULL
    • 唯一約束列可以修改或更新
    • 唯一約束列的值可以重復使用
    • 不能用來定義外鍵
  • 定義唯一約束:UNIQUE,用法同上

22.1.4 檢查約束

  • 檢查約束:用來保證一列(或一組列)中的數(shù)據(jù)滿足一組指定的條件
  • 用途
    • 檢查最小或最大值
    • 指定范圍
    • 只允許特定的值
  • 定義檢查約束:CHECK
  • 有的 DBMS 支持用戶定義數(shù)據(jù)類型,即定義檢查約束的基本簡單數(shù)據(jù)類型
CREATE TABLE module(
    dist_size INT(10) CHECK (dist_size < 1024)
)
ADD CONSTRAINT CHECK (gender LIKE '[MF]')

22.2 索引

  • 索引:用來排序數(shù)據(jù)以加快搜索和排序操作的速度
  • 索引改善了檢索操作的性能,但降低了數(shù)據(jù)插入、修改和刪除的性能(DBMS 必須動態(tài)地更新索引)
  • 索引數(shù)據(jù)可能要占用大量的存儲空間
  • 并非所有的數(shù)據(jù)都適合做縮影,具有更多可能值的數(shù)據(jù)能通過索引得到更多好處
  • 可以在索引中定義多個列,在組合多個列排序時有用
  • 索引的效率隨著表數(shù)據(jù)的變化而變化,需要定期檢查、調整索引
CREATE INDEX name_index ON user(name)

22.3 觸發(fā)器

  • 觸發(fā)器:特殊的存儲過程,在特定的數(shù)據(jù)庫互動發(fā)生時自動執(zhí)行
  • 可以與特定表上的 INSERT、UDPATE、DELETE 操作(或組合)相關聯(lián)
  • 用途
    • 保證數(shù)據(jù)一致,如在 INSERT 或 UPDATE 操作時將字段轉化為大寫
    • 基于某個表的變動在其他表上執(zhí)行活動
    • 進行額外的驗證并根據(jù)需要回退數(shù)據(jù)
    • 計算計算列的值或更新時間戳
  • 約束比觸發(fā)器更快
  • 不同的 DBMS 差異大:CREATE TRIGGER ... FOR ... SET ...

22.4 數(shù)據(jù)庫安全

  • 對數(shù)據(jù)庫管理功能(創(chuàng)建表等)的訪問
  • 對特定數(shù)據(jù)庫或表的訪問
  • 訪問的類型(只讀、對特定列的訪問等)
  • 僅通過視圖或存儲過程對表進行訪問
  • 創(chuàng)建多層次的安全措施,從而允許多種基于登錄的訪問和控制
  • 限制管理用戶賬號的能力

22.5 小結

  • 約束是實施引用完整性的重要部分
  • 索引可以改善數(shù)據(jù)檢索的性能
  • 觸發(fā)器可以用來執(zhí)行運行前后的處理
  • 安全選項可以用來處理數(shù)據(jù)訪問

附錄 A 樣例表腳本


附錄 B 流行的應用程序


附錄 C SQL 語句的語法


附錄 D SQL 數(shù)據(jù)類型


附錄 E SQL 保留字

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容