本文系統梳理 MySQL 核心知識體系,涵蓋 SQL 語言分類、數據定義與操作、完整性約束、字符類型、核心函數、流程控制、子查詢、表連接、事務、視圖、觸發器、存儲過程、索引、臨時表等 23 大模塊,附大量實戰代碼片段,構建從入門到進階的完整知識地圖。
| 類別 | 全稱 | 核心語句 | 作用 |
|---|---|---|---|
| DDL | Data Definition Language | CREATE, ALTER, DROP, TRUNCATE | 定義數據庫對象結構(庫、表、視圖、索引、觸發器) |
| DML | Data Manipulation Language | SELECT, INSERT, UPDATE, DELETE | 操作數據內容 |
| DCL | Data Control Language | GRANT, REVOKE | 控制訪問權限 |
MySQL 語法特點: 字符串用單引號 '...';賦值與比較均用 =;不區分大小寫;無布爾類型(用 TINYINT(1));邏輯運算 AND/OR/NOT 或 &&/||/!。
CREATE DATABASE `school`
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE TABLE `teacher` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`name` VARCHAR(50) NOT NULL COMMENT '姓名',
`class_id` INT NOT NULL COMMENT '班級FK',
`gender` BIT NOT NULL COMMENT '性別',
`age` INT COMMENT '年齡',
`salary` DECIMAL(10,2) COMMENT '薪資',
`birthday` DATETIME COMMENT '生日',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`),
CONSTRAINT `fk_teacher_class` FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`)
ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='教師表';
| 約束類型 | 關鍵字 | 核心規則 | 典型場景 |
|---|---|---|---|
| 主鍵 | PRIMARY KEY (PK) | 非空 + 唯一,一表僅一個(可組合鍵) | 實體唯一標識 |
| 唯一鍵 | UNIQUE (UQ) | 唯一,允許一個 NULL | 身份證、郵箱、手機號 |
| 外鍵 | FOREIGN KEY (FK) | 引用主表 PK/UQ,維護引用完整性 | 訂單-用戶、教師-班級 |
| 檢查約束 | CHECK (CK) | 限制列值範圍/格式(8.0.16+ 強制執行) | age > 0, status IN ('A','B') |
| 默認值 | DEFAULT (DF) | 插入時未指定列自動填充 | created_at=NOW(), status=1 |
| 非空 | NOT NULL | 禁止 NULL | 業務必填字段 |
外鍵級聯動作: CASCADE(級聯刪除/更新)、SET NULL、SET DEFAULT、RESTRICT/NO ACTION(默認阻止)。操作順序: 增刪改查遵循「先主後從、先從後主」原則。
| 類型 | 存儲特性 | 長度語義 | 適用場景 |
|---|---|---|---|
CHAR(n) | 固定長度,右填充空格 | n 字符(0-255) | 定長代碼:MD5、UUID、郵編、身份證前綴 |
VARCHAR(n) | 變長,1-2 字節存長度 + 實際內容 | n 字符(0-65535,受行長限制) | 不定長文本:姓名、地址、描述 |
NCHAR(n) | 固定長度,Unicode,每字符 2 字節 | n 字符 | 多語言固定代碼 |
NVARCHAR(n) | 變長 Unicode | n 字符 | 多語言不定長文本 |
關鍵函數: LEN() 字符數,DATALENGTH() 字節數。CHAR 不回收空間,VARCHAR 自動收縮。
-- 單行
INSERT INTO teacher (name, class_id, gender, age, salary, birthday)
VALUES ('張三', 1, 1, 30, 5000, '1990-01-01');
-- 批量(高效)
INSERT INTO teacher (name, class_id, gender, age, salary, birthday) VALUES
('李四', 1, 0, 28, 4800, '1992-05-10'),
('王五', 2, 1, 35, 6000, '1985-11-20');
-- 複制表數據
INSERT INTO teacher_archive SELECT * FROM teacher WHERE age > 40;
-- 單表
UPDATE teacher SET salary = salary * 1.1 WHERE class_id = 1;
-- 多表連接更新 (MySQL 特有語法)
UPDATE teacher t
JOIN classes c ON t.class_id = c.class_id
SET t.salary = t.salary + 500
WHERE c.class_name = '重點班';
DELETE FROM teacher WHERE age > 60; -- 逐行刪除,寫日志,觸發器生效
TRUNCATE TABLE teacher_archive; -- 瞬時清空,重置自增,無日志,不可回滾
-- 聚合函數(自動過濾 NULL)
SELECT COUNT(*), AVG(salary), MAX(age), MIN(birthday) FROM teacher;
-- 分組統計 + HAVING 過濾組
SELECT class_id, COUNT(*) AS cnt FROM teacher
GROUP BY class_id HAVING cnt >= 5 ORDER BY cnt DESC;
-- 模糊查詢
SELECT * FROM teacher WHERE name LIKE '張%'; -- 張開頭
SELECT * FROM teacher WHERE name LIKE '%老師%'; -- 包含老師
SELECT * FROM teacher WHERE name LIKE '_三'; -- 兩字且第二字為三
SELECT * FROM teacher WHERE name REGEXP '^張.*[0-9]$'; -- 正則
-- NULL 處理
SELECT name, IFNULL(phone, '未填寫') AS phone FROM teacher;
SELECT * FROM teacher WHERE phone IS NULL / IS NOT NULL;
-- 分頁 (LIMIT offset, count)
SELECT * FROM teacher ORDER BY id LIMIT 0, 10; -- 第 1 頁
SELECT * FROM teacher ORDER BY id LIMIT 10, 10; -- 第 2 頁
-- 簡單 CASE(等值判斷)
SELECT name,
CASE class_id WHEN 1 THEN '一班' WHEN 2 THEN '二班' ELSE '其他' END AS class_name
FROM teacher;
-- 搜索 CASE(範圍/表達式判斷,支援 NULL 判斷)
SELECT name, age,
CASE
WHEN age < 30 THEN '青年'
WHEN age BETWEEN 30 AND 45 THEN '中堅'
WHEN age IS NULL THEN '未知'
ELSE '資深'
END AS age_group
FROM teacher;
-- IF ELSE
IF avg_score >= 60 THEN
SELECT '及格';
ELSE
SELECT '不及格';
END IF;
-- WHILE 循環
WHILE counter < total DO
UPDATE scores SET value = value + 2 WHERE subject_id = sub_id AND value < 60;
SET counter = (SELECT COUNT(*) FROM scores WHERE subject_id = sub_id AND value < 60);
END WHILE;
-- LOOP + LEAVE + ITERATE
loop_label: LOOP
SET i = i + 1;
IF i > 10 THEN LEAVE loop_label; END IF;
IF i % 2 = 0 THEN ITERATE loop_label; END IF;
-- 處理奇數
END LOOP;
WHERE col = (SELECT ...) / IN (SELECT ...) / EXISTS (SELECT ...)SELECT * FROM (SELECT ... ) t WHERE ... —— 必須起別名,列必須命名SELECT (SELECT name FROM user WHERE id=t.uid) AS uname FROM orders t分頁優化: ROW_NUMBER() OVER (ORDER BY id) 窗口函數(8.0+)替代 LIMIT offset, count 深分頁性能問題。
-- 內連接:雙方匹配
SELECT s.name, c.class_name FROM student s INNER JOIN class c ON s.class_id = c.id;
-- 左連接:左表全保留,右表無匹配則 NULL
SELECT s.name, c.class_name FROM student s LEFT JOIN class c ON s.class_id = c.id;
-- 右連接:右表全保留
SELECT s.name, c.class_name FROM student s RIGHT JOIN class c ON s.class_id = c.id;
-- 全連接:左右並集(MySQL 不支援 FULL JOIN,用 UNION 模擬)
SELECT * FROM student LEFT JOIN class ON ...
UNION
SELECT * FROM student RIGHT JOIN class ON ...;
START TRANSACTION;
UPDATE account SET balance = balance - 500 WHERE user = 'A';
UPDATE account SET balance = balance + 500 WHERE user = 'B';
-- 檢查錯誤
IF @@ERROR <> 0 THEN ROLLBACK; ELSE COMMIT; END IF;
-- 或
SAVEPOINT sp1;
-- 操作
ROLLBACK TO sp1; -- 回滾到保存點
RELEASE SAVEPOINT sp1;
隔離級別: READ UNCOMMITTED < READ COMMITTED < REPEATABLE READ (默認) < SERIALIZABLE。MVCC 實現 RR 級別下的非鎖定讀。
CREATE VIEW v_teacher_class AS
SELECT t.id, t.name, c.class_name
FROM teacher t JOIN class c ON t.class_id = c.id;
SELECT * FROM v_teacher_class WHERE class_name = '一班';
-- 可更新視圖條件:單表、無聚合、無 DISTINCT、無 GROUP BY、包含 PK
-- AFTER INSERT:新增後同步統計
CREATE TRIGGER tr_class_after_insert AFTER INSERT ON class
FOR EACH ROW
BEGIN
UPDATE school_stat SET class_count = class_count + 1 WHERE school_id = NEW.school_id;
END;
-- 兩大臨時表:NEW (INSERT/UPDATE 後), OLD (UPDATE/DELETE 前)
CREATE TRIGGER tr_teacher_audit BEFORE UPDATE ON teacher
FOR EACH ROW
BEGIN
IF NEW.salary <> OLD.salary THEN
INSERT INTO salary_log (teacher_id, old_salary, new_salary, change_time)
VALUES (OLD.id, OLD.salary, NEW.salary, NOW());
END IF;
END;
CREATE PROCEDURE sp_get_teacher_by_class (
IN p_class_name VARCHAR(50),
IN p_gender BIT,
OUT p_total INT
)
BEGIN
DECLARE v_class_id INT;
SELECT id INTO v_class_id FROM class WHERE name = p_class_name;
SELECT * FROM teacher WHERE class_id = v_class_id AND gender = p_gender;
SELECT COUNT(*) INTO p_total FROM teacher WHERE class_id = v_class_id AND gender = p_gender;
END;
-- 調用
CALL sp_get_teacher_by_class('一班', 1, @total);
SELECT @total;
CREATE PROCEDURE sp_page_teacher (
IN p_page_index INT, IN p_page_size INT, OUT p_total_pages INT
)
BEGIN
DECLARE v_total INT;
SELECT COUNT(*) INTO v_total FROM teacher;
SET p_total_pages = CEILING(v_total / p_page_size);
SELECT * FROM teacher
ORDER BY id
LIMIT (p_page_index - 1) * p_page_size, p_page_size;
END;
(a,b,c) 支援 a/a,b/a,b,c 查詢。| 類型 | 語法 | 作用域 | 生命周期 |
|---|---|---|---|
| 局部臨時表 | CREATE TABLE #t (...) | 當前會話 | 會話結束自動銷毀 |
| 全局臨時表 | CREATE TABLE ##t (...) | 所有會話可見 | 創建會話結束銷毀 |
| 表變量 | DECLARE @t TABLE (...) | 批處理/存儲過程內 | 批次結束銷毀,內存優先 |
MySQL 知識體系如金字塔:SQL 基礎語法 為基石,約束與類型 保障數據質量,查詢與函數 滿足業務檢索,流程控制 賦予邏輯靈活性,事務 保證一致性,視圖/觸發器/存儲過程 封裝復用業務規則,索引 決定性能上限。系統掌握這 15 大模塊,並能靈活組合解決實際問題,即為合格的 MySQL 開發與運維工程師。