閱讀總結
用于了解 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 行
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
2.6 限制結果
# MySQL、MariaDB、PostgreSQL、SQLite
SELECT name from user LIMIT 10
# 第 5 行后的 10 行
SELECT name from user LIMIT 10 OFFSET 5
2.7 使用注釋
SELECT name FROM user -- 注釋
# 注釋
/*
* 注釋
*/
2.8 小結
第 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
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
3.5 小結
第 4 課 過濾數(shù)據(jù)
4.1 使用 WHERE 子句
SELECT * from user WHERE name = 'xiaoming'
- WHERE 指定搜索條件(過濾條件)
- 使用 SQL 過濾而不是應用過濾
4.2 WHERE 子句操作符
| 操作符 |
說明 |
| = |
|
| <> |
不等于 |
| != |
不等于 |
| < |
|
| <= |
|
| > |
|
| >= |
|
| BETWEEN ... AND ... |
|
| IS NULL |
|
4.2.1 檢查單個值
SELECT * from user WHERE id < 10
4.2.2 不匹配檢查
SELECT * from user WHERE npm_user <> 1
4.2.3 范圍值檢查
SELECT * from user WHERE id BETWEEN 10 AND 100
4.2.3 空值檢查
SELECT * from user WHERE email IS NULL
4.3 小結
第 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 小結
第 6 課 用通配符進行過濾
6.1 LIKE 操作符
- 通配符(wildcard):用來匹配值的一部分的特殊字符
- 搜索模式(search pattern):由字面值、通配符或兩者組合構成的搜索條件
- 謂詞(predicate):LIKE 作為謂詞
6.1.1 百分號(%)通配符
# xiao 開頭的 name
SELECT *
FROM user
WHERE name LIKE 'xiao%'
- %:任何字符出現(xiàn)任意次數(shù)
- 根據(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ù) |
說明 |
| LEFT |
返回字符串左邊的字符 |
| LENGTH |
返回字符串長度 |
| LOWER |
返回字符串小寫 |
| UPPER |
返回字符串大寫 |
| LTRIM |
去字符串左邊空格 |
| RIGHT |
返回字符串右邊的字符 |
| RTRIM |
去字符串右邊空格 |
| SOUNDEX |
返回字符串的 SOUNDEX 值(語音描述) |
8.2.2 日期和時間處理函數(shù)
- DBMS 都有自己的日期時間形式和處理函數(shù)
- 高效排序或過濾
- 節(jié)省存儲空間
- 可移植性差
8.2.3 數(shù)值處理函數(shù)
| 函數(shù) |
說明 |
| ABS |
絕對值 |
| COS |
余弦值 |
| EXP |
指數(shù)值 |
| PI |
圓周率 |
| SIN |
正弦值 |
| SQRT |
平方根 |
| TAN |
正切 |
8.3 小結
第 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
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
9.1.4 MIN() 函數(shù)
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
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 |
| 對產生的輸出排序 |
對行分組,輸出不一定是分組的順序 |
| 任意列都可以使用 |
只能使用選擇列或表達式列 |
| 不一定需要 |
在與聚集函數(shù)一起使用時必要 |
10.5 SELECT 子句順序
- SELECT
- FROM
- WHERE
- GROUP BY
- HAVING
- 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)結
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)結多個表
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 對組合查詢結果排序
14.3 小結
第 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.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
- DBMS 中的 UPDATE 權限
- UPDATE 語句組成
16.2 刪除數(shù)據(jù)
DELETE FROM user
WHERE name = 'a'
- DELETE
- 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ù)的列幾乎沒有限制
- 復雜的表結構更改一般需要手動刪除過程
- 用新的列布局創(chuàng)建一個新表
- 用 INSERT SELECT 從舊表復制數(shù)據(jù)倒新表
- 檢驗包含所需數(shù)據(jù)的新表
- 重命名舊表(可以刪除)
- 用舊表原來的名字重命名新表
- 重新創(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)建視圖
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 小結
第 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 保留字