首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

SQL 語言全維度解析:DDL/DML/DQL/DCL 分類與核心語法精講

     編輯:MySQL 綜合教學

SQL 四大語言類別速覽

類別全稱核心動作典型語句佔比參考
DDLData Definition Language定義/管理資料庫物件CREATE, ALTER, DROP, TRUNCATE, RENAME~10%
DMLData Manipulation Language操作表中資料記錄INSERT, UPDATE, DELETE, REPLACE, MERGE~25%
DQLData Query Language查詢資料並返回結果集SELECT, WITH (CTE), SHOW, EXPLAIN~60%
DCLData Control Language權限控制與事務管理GRANT, REVOKE, COMMIT, ROLLBACK, SAVEPOINT~5%

DDL:物件生命週期管理

資料庫層級

CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER DATABASE app_db CHARACTER SET utf8mb4;  -- 僅影響後續建表
DROP DATABASE app_db;

資料表層級

-- 建表最佳實踐:顯式引擎、字符集、註釋、主鍵、索引
CREATE TABLE `orders` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用戶ID',
  `order_no` CHAR(20) NOT NULL COMMENT '訂單號',
  `amount` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '金額',
  `status` TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0待付款 1已付款 2已發貨 3完成 4取消',
  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
  `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_order_no` (`order_no`),
  KEY `idx_user_status` (`user_id`, `status`),
  KEY `idx_created` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='訂單主表';

-- 修改表結構 (Online DDL 5.6+ 大多操作不鎖表)
ALTER TABLE orders ADD COLUMN `pay_time` DATETIME NULL COMMENT '支付時間' AFTER `status`;
ALTER TABLE orders MODIFY `amount` DECIMAL(12,2) NOT NULL DEFAULT 0.00;
ALTER TABLE orders DROP INDEX `idx_created`;

索引與約束

-- 索引類型
CREATE INDEX idx_name ON users(name);                    -- 普通
CREATE UNIQUE INDEX uk_email ON users(email);            -- 唯一
CREATE FULLTEXT INDEX ft_content ON articles(content);   -- 全文 (MyISAM/InnoDB 5.6+)
ALTER TABLE orders ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id);

DML:資料增刪改核心模式

INSERT 多種寫法

-- 單行
INSERT INTO users(name, email) VALUES('Alice', 'alice@example.com');

-- 多行批次 (高效,單次網絡往返)
INSERT INTO users(name, email) VALUES
  ('Bob', 'bob@example.com'),
  ('Cathy', 'cathy@example.com');

-- 插入查詢結果 (ETL 常用)
INSERT INTO dw.daily_summary(dt, total_orders, total_amount)
SELECT DATE(created_at), COUNT(*), SUM(amount) FROM orders
WHERE created_at >= '2024-01-01' GROUP BY DATE(created_at);

-- 衝突處理 (MySQL 8.0.19+ 支援 ON DUPLICATE KEY UPDATE 別名)
INSERT INTO counters(id, cnt) VALUES('page_view', 1)
ON DUPLICATE KEY UPDATE cnt = cnt + 1;

UPDATE 安全模式與優化

-- 必須帶 WHERE,防止全表誤更新 (sql_safe_updates=ON 時強制)
UPDATE orders SET status = 1, pay_time = NOW()
WHERE order_no = 'ORD202401150001' AND status = 0;  -- 條件含舊值防併發覆蓋

-- 大表分批更新模板
DELIMITER //
CREATE PROCEDURE batch_update_status()
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE v_id BIGINT;
  DECLARE cur CURSOR FOR SELECT id FROM orders WHERE status = 0 AND created_at < '2024-01-01' LIMIT 1000;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
  OPEN cur;
  REPEAT
    FETCH cur INTO v_id;
    IF NOT done THEN
      UPDATE orders SET status = 4 WHERE id = v_id AND status = 0;
      COMMIT;
      DO SLEEP(0.01);
    END IF;
  UNTIL done END REPEAT;
  CLOSE cur;
END//
DELIMITER ;

DELETE vs TRUNCATE

特性DELETETRUNCATE
可帶 WHERE是否
觸發器觸發不觸發
自增計數器保留歸零
事務支援支援 (可回滾)隱式提交 (不可回滾)
速度逐行刪除,慢釋放頁面,極快
Binlog 記錄逐行 (ROW 模式)單條 DDL 語句

DQL:查詢進階與優化要點

核心子句執行順序

SELECT select_list          -- 5
FROM table_references       -- 1
WHERE where_condition       -- 2
GROUP BY group_list         -- 3
HAVING having_condition     -- 4
ORDER BY order_list         -- 6
LIMIT offset, row_count     -- 7

高效分頁 (避免深分頁 OFFSET 掃描)

-- 鍵值分頁 (適合唯一遞增主鍵/索引)
SELECT * FROM orders WHERE id > 100000 ORDER BY id LIMIT 20;

-- 子查詢延遲關聯
SELECT o.* FROM orders o
JOIN (SELECT id FROM orders WHERE user_id = 123 ORDER BY id LIMIT 100000, 20) t USING (id);

CTE (Common Table Expression) 簡化複雜查詢

WITH ranked AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY amount DESC) rn
  FROM orders WHERE created_at >= '2024-01-01'
)
SELECT * FROM ranked WHERE rn <= 3;  -- 每用戶金額 Top3

DCL:權限體系與事務控制

權限模型 (MySQL 8.0 角色化)

-- 建立角色
CREATE ROLE 'app_read', 'app_write';
GRANT SELECT ON app_db.* TO 'app_read';
GRANT INSERT, UPDATE, DELETE ON app_db.* TO 'app_write';

-- 用戶授予角色
CREATE USER 'api_svc'@'%' IDENTIFIED BY 'pass';
GRANT 'app_read', 'app_write' TO 'api_svc'@'%';
SET DEFAULT ROLE ALL TO 'api_svc'@'%';  -- 自動啟用

-- 撤銷
REVOKE 'app_write' FROM 'api_svc'@'%';

事務控制

START TRANSACTION;
  UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
  UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
  -- 檢查業務邏輯
  IF (SELECT balance FROM accounts WHERE user_id = 1) < 0 THEN
    ROLLBACK;
  ELSE
    COMMIT;
  END IF;

-- 保存點 (部分回滾)
SAVEPOINT sp1;
DELETE FROM logs WHERE created_at < '2023-01-01';
ROLLBACK TO sp1;  -- 僅回滾 DELETE

實戰建議:SQL 開發規範摘要

  1. 命名:庫表欄位小寫 + 下劃線 (snake_case);主鍵 id、外鍵 xxx_id、時間 xxx_at/on、狀態 status、標誌 is_xxx。
  2. SELECT 禁用 *:明確列出欄位,減少網絡傳輸、利用覆蓋索引、避免 schema 變更衝擊。
  3. WHERE 必須命中索引:EXPLAIN 驗證 type=ref/range/eq_ref,避免 ALL/index。
  4. 大事務拆小:單事務 < 5000 行、< 1 秒,降低鎖競爭、主從延遲、Undo Log 壓力。
  5. DDL 線上執行:5.6+ 使用 ALGORITHM=INPLACE, LOCK=NONE;大表變更走 pt-online-schema-change/gh-ost。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved