一、SQL 與關聯式資料庫核心概念
什麼是 SQL?
- Structured Query Language:ANSI/ISO 標準查詢語言,最新 SQL:2016
- 主流資料庫 (SQL Server, Oracle, PostgreSQL, MySQL) 皆支援核心子集,各有擴充
關鍵術語對照
| 術語 | 定義 | SQL Server 實體 |
| 資料庫 | 邏輯容器,含結構描述、物件、資料、權限 | `CREATE DATABASE` |
| 結構描述 | 物件命名空間,擁有者/權限邊界 | `dbo`, `Sales`, `Person` |
| 資料表 | 列 (Row) + 欄位 組成的關聯實體 | `CREATE TABLE` |
| 欄位 | 單一屬性,有名稱、資料型別、約束 | `Column` 定義 |
| 列 / 記錄 | 單一實體實例,橫向一筆資料 | `Row` / `Record` |
| 欄位值 | 列與欄位交叉的單一值 | `Field` / `Cell` |
| 結果集 | 查詢回傳的暫時表格 | `Result Set` |
| 主鍵 | 唯一識別列,非 NULL、唯一 | `PRIMARY KEY` |
| 外鍵 | 參考他表主鍵,維護參考完整性 | `FOREIGN KEY` |
二、四大基礎資料操作查詢 (DML)
| 陳述式 | 用途 | 標準語法 | 關鍵特性 |
| SELECT | 查詢/擷取資料 | `SELECT col1, col2 FROM table WHERE condition;` | 唯讀、選項最多 (JOIN、GROUP BY、窗口函數) |
| INSERT | 新增資料列 | `INSERT INTO table (col1, col2) VALUES (val1, val2);` | 可 `INSERT ... SELECT` 批量載入 |
| UPDATE | 修改現有資料 | `UPDATE table SET col1=val1 WHERE condition;` | 無 WHERE 將更新全表,**極度危險** |
| DELETE | 刪除資料列 | `DELETE FROM table WHERE condition;` | 無 WHERE 將清空全表,**極度危險** |
三、SELECT 基礎查詢模式
1. 指定欄位
SELECT FirstName, LastName, Email FROM Customers;
2. 所有欄位 (開發/除錯用,生產避免)
SELECT * FROM Customers;
3. 別名
SELECT FirstName AS FN, LastName AS LN FROM Customers;
-- 或
SELECT FirstName FN, LastName LN FROM Customers;
4. 運算式與常數
SELECT ProductName, UnitPrice * 1.05 AS PriceWithTax, 'Active' AS Status
FROM Products;
四、WHERE 條件篩選完整指南
比較運算子
| 運算子 | 含義 | 範例 |
| `=` | 等於 | `WHERE Status = 'Active'` |
| `<>` / `!=` | 不等於 | `WHERE Status <> 'Deleted'` |
| `>` | 大於 | `WHERE Price > 100` |
| `<` | 小於 | `WHERE Price < 50` |
| `>=` | 大於等於 | `WHERE Qty >= 10` |
| `<=` | 小於等於 | `WHERE Qty <= 5` |
邏輯運算子與優先序
-- 優先序:括號 > NOT > AND > OR
WHERE (Category = 'Electronics' OR Category = 'Books')
AND Price > 50
AND NOT Discontinued;
-- 等價展開
WHERE (Category = 'Electronics' AND Price > 50 AND NOT Discontinued)
OR (Category = 'Books' AND Price > 50 AND NOT Discontinued);
進階篩選運算子
| 運算子 | 語法 | 範例 | 注意 |
| `BETWEEN` | `col BETWEEN low AND high` | `WHERE Price BETWEEN 10 AND 100` | **包含邊界**,等價 `>= low AND <= high` |
| `IN` | `col IN (val1, val2, ...)` | `WHERE Status IN ('Active','Pending')` | 子查詢版見進階篇 |
| `LIKE` | `col LIKE pattern` | `WHERE Name LIKE 'A%'` | `%` 任意長度,`_` 單字元,`[]` 範圍,`[^]` 排除 |
| `IS NULL` | `col IS NULL` | `WHERE ShipDate IS NULL` | `= NULL` 永遠 FALSE,必須用 `IS NULL` |
| `IS NOT NULL` | `col IS NOT NULL` | `WHERE ShipDate IS NOT NULL` | |
字串/日期/數值字面值語法
-- 字串:單引號,單引號轉義用雙單引號
WHERE Name = 'O''Brien'
-- 日期:ISO 8601 格式最安全 (不受語言/日期格式設定影響)
WHERE OrderDate >= '20230101' -- 日期
WHERE OrderDate >= '2023-01-01T00:00:00' -- 日期時間
WHERE OrderDate >= '2023-01-01T00:00:00.000+08:00' -- 含時區
-- 數值:直接書寫,科學記號支援
WHERE Price > 1.23e2 -- 123
五、INSERT 進階模式
-- 1. 明確欄位 (推薦,順序無關)
INSERT INTO Customers (Email, FirstName, LastName)
VALUES ('john@example.com', 'John', 'Doe');
-- 2. 多列單陳述式 (2008+)
INSERT INTO Products (Name, Price) VALUES
('Widget A', 10.00), ('Widget B', 20.00), ('Widget C', 15.00);
-- 3. INSERT ... SELECT (批量/轉換)
INSERT INTO Archive_Orders (OrderID, CustomerID, OrderDate, TotalAmt)
SELECT OrderID, CustomerID, OrderDate, TotalAmt
FROM Orders
WHERE OrderDate < '2022-01-01';
-- 4. OUTPUT 子句取回身分識別/計算值 (2005+)
INSERT INTO Orders (CustomerID, OrderDate)
OUTPUT INSERTED.OrderID, INSERTED.OrderDate
VALUES (123, GETDATE());
六、UPDATE 與 DELETE 安全鐵律
- 永遠先寫 SELECT 驗證影響範圍:
-- UPDATE 前
SELECT * FROM Products WHERE Category = 'Electronics';
-- 確認後
UPDATE Products SET Price = Price * 1.1 WHERE Category = 'Electronics';
- 使用交易包裝:
BEGIN TRAN;
UPDATE ...; DELETE ...;
-- 驗證 @@ROWCOUNT、資料正確性
COMMIT; -- 或 ROLLBACK;
- 大量更新/刪除分批執行**:避免長鎖定、記錄檔暴漲、鎖升級
- 生產環境嚴禁無 WHERE 的 UPDATE/DELETE**:建立 DDL 觸發器攔截或資料庫審計
七、NULL 三值邏輯核心規則
- `NULL = NULL` → `UNKNOWN` (非 TRUE/FALSE)
- `NULL <> NULL` → `UNKNOWN`
- `NULL > 5` → `UNKNOWN`
- `WHERE` / `HAVING` / `ON` / `CASE WHEN` 只接受 `TRUE`,`UNKNOWN`/`FALSE` 皆被過濾
- `NOT UNKNOWN` → `UNKNOWN` (故 `NOT IN` 含 NULL 會全掉)
- 判斷 NULL 唯一標準:`IS NULL` / `IS NOT NULL`
八、常見新手錯誤 TOP 10
- `WHERE DateCol = '2023-01-01'` 含時間部分 → 改 `WHERE DateCol >= '20230101' AND DateCol < '20230102'`
- `WHERE VarcharCol = N'Unicode'` 導致索引掃描 → 參數型別對齊
- `UPDATE Table SET Col = NULL WHERE Col = ''` 空字串 ≠ NULL
- `DELETE FROM Table` 忘記 WHERE → 全表清空
- `SELECT *` 生產查詢 → 明確列出欄位
- `INSERT INTO Table VALUES (...)` 不指定欄位 → 結構變更即報錯
- `JOIN` 缺少 ON 條件 → 笛卡兒積
- `GROUP BY` 缺少 SELECT 非彙總欄位 → 語法錯誤
- 字串拼接 `WHERE 'A' + 'B' = 'AB'` 隱式轉換陷阱
- 未使用參數化查詢 → SQL 注入風險、計劃快取汙染
下一篇將進入 SELECT 進階選項:`ORDER BY` 排序、`DISTINCT` 去重、彙總函數 `COUNT/SUM/AVG/MIN/MAX`、`GROUP BY` 分組、`HAVING` 分組篩選、窗口函數基礎。