《SQL 必知必會(huì)》- 閱讀索引

閱讀總結(jié)

用于了解 SQL 的基礎(chǔ)知識(shí)還是非常好的。

在使用時(shí)可以具體看 DBMS 文檔。

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


[toc]


第 1 課 了解 SQL

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

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

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

1.1.2 表

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

1.1.3 列

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

1.1.3 行

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

1.1.5 主鍵

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

1.2 什么是 SQL

  • SQL:結(jié)構(gòu)化查詢語言(Structured Query Language)
    • 不是某個(gè) DBMS 專用的
    • 簡單易學(xué),強(qiáng)描述性
    • 強(qiáng)大
  • SQL 的擴(kuò)展:針對(duì)特定 DBMS 的簡化特定操作執(zhí)行的方法
  • 標(biāo)準(zhǔn) SQL 由 ANSI 標(biāo)準(zhǔn)委員會(huì)管理

1.3 動(dòng)手實(shí)踐

1.4 小結(jié)

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

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

2.1 SELECT 語句

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

2.2 檢索單個(gè)列

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

2.3 檢索多個(gè)列

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

2.4 檢索所有列

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

2.5 檢索不同的值

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

2.6 限制結(jié)果

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

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

2.7 使用注釋

SELECT name FROM user -- 注釋
# 注釋
/*
 * 注釋
 */
  • -- 行內(nèi)
  • # 單行
  • /* */ 多行

2.8 小結(jié)

  • SELECT 語句檢索
  • 注釋

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

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

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

3.2 按多個(gè)列排序

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

3.3 按列位置排序

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

3.4 指定排序方向

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

3.5 小結(jié)

  • ORDER BY 子句

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

4.1 使用 WHERE 子句

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

4.2 WHERE 子句操作符

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

4.2.1 檢查單個(gè)值

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 小結(jié)

  • WHERE 子句過濾

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

5.1 組合 WHERE 子句

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

5.1.1 AND 操作符

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

5.1.2 OR 操作符

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

5.1.3 求值順序

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

5.2 IN 操作符

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

5.3 NOT 操作符

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

5.4 小結(jié)

  • AND/OR
  • 求值順序
  • NOT

第 6 課 用通配符進(jìn)行過濾

6.1 LIKE 操作符

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

6.1.1 百分號(hào)(%)通配符

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

6.1.2 下劃線(_)通配符

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

6.1.3 方括號(hào)([])通配符

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

6.2 使用通配符的技巧

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

6.3 小結(jié)

  • 什么是通配符
  • 如何在 WHERE 子句中使用
  • 注意點(diǎn)

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

7.1 計(jì)算字段

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

7.2 拼接字段

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

7.3 執(zhí)行算術(shù)計(jì)算

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

7.4 小結(jié)

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

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

8.1 函數(shù)

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

8.2 使用函數(shù)

  • 處理文本字符串
  • 數(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í)間處理函數(shù)

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

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

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

8.3 小結(jié)

  • 有用
  • 各 DBMS 不一致

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

9.1 聚集函數(shù)

  • 只需要匯總數(shù)據(jù)而不需要實(shí)際檢索,如
    • 滿足某個(gè)條件的行的行數(shù)
    • 某些行的和
    • 某些列的最大值、平均值等
  • 聚集函數(shù)(aggregate function):對(duì)某些行運(yùn)行的函數(shù),計(jì)算并返回一個(gè)值
  • 在各 DMBS 中實(shí)現(xiàn)相當(dāng)一致
函數(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/%'
  • 只能用于單列,多個(gè)列的平均值必須使用多個(gè) AVG()
  • 對(duì) NULL
    • 值為 NULL 的行會(huì)被忽略

9.1.1 COUNT() 函數(shù)

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

9.1.3 MAX() 函數(shù)

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

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
  • 對(duì)非數(shù)值忽略
  • 對(duì) NULL 忽略

9.2 聚集不同的值

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

9.3 組合聚集函數(shù)

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

9.4 小結(jié)

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

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

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

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

10.2 創(chuàng)建分組

# 每個(gè)包及其版本數(shù)
SELECT name, COUNT(*) AS version_count 
FROM module 
GROUP BY name
  • GROUP BY 子句可以包含任意數(shù)目的列
  • 列可以是檢索列或有效表達(dá)式(不能是聚集函數(shù))
  • NULL 會(huì)被作為一個(gè)分組返回
  • 放在 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ù)分組后進(jìn)行過濾,WHERE 在分組前進(jìn)行過濾

10.4 分組和排序

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

10.5 SELECT 子句順序

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

10.6 小結(jié)

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

第 11 課 使用子查詢

11.1 子查詢

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

11.2 利用子查詢進(jìn)行過濾

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

11.3 作為計(jì)算字段使用子查詢

# 每個(gè)有包的作者的包的數(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 小結(jié)

  • 子查詢及如何使用

第 12 課 聯(lián)結(jié)表

12.1 聯(lián)結(jié)

  • JOIN

12.1.1 關(guān)系表

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

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

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

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

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

12.2.1 WHERE 子句的重要性

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

12.2.2 內(nèi)聯(lián)結(jié)

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

12.2.3 聯(lián)結(jié)多個(gè)表

  • 同兩張表
  • 過多的聯(lián)結(jié)表耗費(fèi)性能

12.3 小結(jié)

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

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

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)結(jié)

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

13.2.1 自聯(lián)結(jié)

# 和 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)結(jié)遠(yuǎn)比子查詢快

13.2.2 自然聯(lián)結(jié)

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

13.3.3 外聯(lián)結(jié)

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

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

# 所有沒有發(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)結(jié)和聯(lián)結(jié)條件

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

13.5 小結(jié)

  • 聯(lián)結(jié)類型
  • 聯(lián)結(jié)中聚集
  • 注意事項(xiàng)

第 14 課 組合查詢

14.1 組合查詢

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

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 會(huì)將 UNION 優(yōu)化為一條 SELECT 語句

14.2.2 UNION 規(guī)則

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

14.2.3 包含或取消重復(fù)的行

  • UNION 會(huì)過濾重復(fù)的行
  • UNION ALL 包含重復(fù)的行,這是 WHERE 無法完成的

14.2.4 對(duì)組合查詢結(jié)果排序

  • ORDER BY 放在所有 SELECT 之后

14.3 小結(jié)

  • UNION 組合查詢語句

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

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

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

15.1.1 插入完整的行

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

15.1.2 插入部分行

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

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 對(duì)應(yīng),而無須列名一致

15.2 從一個(gè)表復(fù)制到另一個(gè)表

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

15.3 小結(jié)

  • 使用 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 權(quán)限
  • UPDATE 語句組成
    • 要更新的表
    • 列名和它們的新值
    • 行的過濾條件

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

DELETE FROM user
WHERE name = 'a'
  • DELETE
    • 刪除特定行,注意 WHERE
    • 刪除所有行
  • DBMS 中的 DELETE 權(quán)限
  • 刪除的是行而不是表
  • 使用 TRUNCATE TABLE 來刪除所有行更快(因?yàn)椴挥涗洈?shù)據(jù)的變動(dòng))

16.3 更新和刪除的指導(dǎo)原則

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

16.4 小結(jié)

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

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

17.1 創(chuàng)建表

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

17.1.1 表創(chuàng)建基礎(chǔ)

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
)
  • 每個(gè)表列要么是 NULL 列,要么是 NOT NULL 列
  • 允許 NULL 值的列不能作為主鍵
  • 有的 DBMS 需要指定關(guān)鍵詞 NULL

17.1.3 指定默認(rèn)值

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;
  • 對(duì) ALTER TABLE 的限制
    • 盡量避免在表中包含數(shù)據(jù)時(shí)更新
    • 所有 DBMS 都支持增加列
    • 許多 DBMS 不允許刪除或更改列
    • 多少 DMBS 允許重命名列
    • 許多 DBMS 限制對(duì)有數(shù)據(jù)的列更改,對(duì)無數(shù)據(jù)的列幾乎沒有限制
  • 復(fù)雜的表結(jié)構(gòu)更改一般需要手動(dòng)刪除過程
    1. 用新的列布局創(chuàng)建一個(gè)新表
    2. 用 INSERT SELECT 從舊表復(fù)制數(shù)據(jù)倒新表
    3. 檢驗(yàn)包含所需數(shù)據(jù)的新表
    4. 重命名舊表(可以刪除)
    5. 用舊表原來的名字重命名新表
    6. 重新創(chuàng)建觸發(fā)器、存儲(chǔ)過程、索引和外鍵

17.3 刪除表

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

17.4 重命名表

  • 不同 DBMS 有差別,MySQL 用 RENAME

17.5 小結(jié)

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

第 18 課 使用視圖

18.1 視圖

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

18.1.1 為什么使用視圖

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

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

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

18.2 創(chuàng)建視圖

  • CREATE VIEW
  • DROP VIEW

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

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 使用視圖與計(jì)算字段

18.3 小結(jié)

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

第 19 課 使用存儲(chǔ)的過程

19.1 存儲(chǔ)過程

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

19.2 為什么要使用存儲(chǔ)過程

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

19.3 執(zhí)行存儲(chǔ)過程

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

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

19.5 小結(jié)

  • 見具體 DBMS

第 20 課 管理事務(wù)處理

20.1 事務(wù)處理

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

20.2 控制事務(wù)處理

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

20.2.1 使用 ROLLBACK

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

20.2.2 使用 COMMIT

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

20.2.3 使用保留點(diǎn)

SAVEPOINT delete1;
# DELTE ...
ROLLBACK TO delete1;
  • 保留點(diǎn)越多越好,以進(jìn)行靈活地回退

20.3 小結(jié)

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

第 21 課 使用游標(biāo)

21.1 游標(biāo)

  • 結(jié)果集(result set):SQL 查詢所檢索出的結(jié)果
  • 游標(biāo)(cursor):一個(gè)存儲(chǔ)在 DBMS 服務(wù)器上的數(shù)據(jù)庫查詢,不是一條 SQL 語句,而是被該語句檢索出來的結(jié)果集。應(yīng)用程序可以根據(jù)需要滾動(dòng)或?yàn)g覽其中的數(shù)據(jù)
  • 對(duì)于 WEB 應(yīng)用用處不大,因?yàn)閼?yīng)用服務(wù)器是數(shù)據(jù)庫客戶端而不是最終用戶

21.2 使用游標(biāo)

21.3 小結(jié)


第 22 課 高級(jí) SQL 特性

22.1 約束

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

22.1.1 主鍵

  • 主鍵是一種特殊的約束,用來保證一列(或一組列)中的值是唯一的,且永不改動(dòng)
  • 任意列只要滿足以下條件,都可以用于主鍵
    • 任意兩行的主鍵值都不相同
    • 列中不允許 NULL 值
    • 列從不修改或更新
    • 主鍵值不能重用
  • 定義主鍵:創(chuàng)建表時(shí)或 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 不允許刪除在另一個(gè)表中具有關(guān)聯(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ū)別:
    • 表可以包含多個(gè)唯一約束
    • 唯一約束列可以包含 NULL
    • 唯一約束列可以修改或更新
    • 唯一約束列的值可以重復(fù)使用
    • 不能用來定義外鍵
  • 定義唯一約束: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 必須動(dòng)態(tài)地更新索引)
  • 索引數(shù)據(jù)可能要占用大量的存儲(chǔ)空間
  • 并非所有的數(shù)據(jù)都適合做縮影,具有更多可能值的數(shù)據(jù)能通過索引得到更多好處
  • 可以在索引中定義多個(gè)列,在組合多個(gè)列排序時(shí)有用
  • 索引的效率隨著表數(shù)據(jù)的變化而變化,需要定期檢查、調(diào)整索引
CREATE INDEX name_index ON user(name)

22.3 觸發(fā)器

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

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

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

22.5 小結(jié)

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

附錄 A 樣例表腳本


附錄 B 流行的應(yīng)用程序


附錄 C SQL 語句的語法


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


附錄 E SQL 保留字

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容