💾 什麼是資料庫?
📖 定義
資料庫(Database, DB)是系統地結構化的資料集合。DBMS(Database Management System,資料庫管理系統)是建立、管理和存取資料庫的軟體。資料庫可以高效地儲存和檢索資料,允許多個使用者同時安全存取。
🎯 用類比理解
圖書館系統
將資料庫比作圖書館:
- 資料庫: 整個圖書館
- 表: 各個區域(小說、科學、歷史等)
- 行(Row): 單獨的書
- 列(Column): 書的屬性(標題、作者、出版年等)
- 主鍵(Primary Key): 圖書唯一編號
- DBMS: 圖書管理員和管理系統
圖書館 (資料庫)
├─ 小說區 (表)
│ ├─ 書1: 哈利波特, J.K.羅琳, 1997
│ ├─ 書2: 魔戒, 托爾金, 1954
│ └─ 書3: 小王子, 聖修伯里, 1943
├─ 科學區 (表)
│ ├─ 書1: 宇宙, 卡爾·薩根, 1980
│ └─ 書2: 自私的基因, 理查·道金斯, 1976
└─ 借閱記錄 (表)
├─ 記錄1: 會員123, 哈利波特, 2024-01-15
└─ 記錄2: 會員456, 宇宙, 2024-01-20
⚙️ 工作原理
1. 資料庫結構
資料庫 (Database)
└─ 表 (Table)
├─ 行 (Row/Record) - 單個資料項
│ └─ 例: 一個使用者的資訊
└─ 列 (Column/Field) - 資料屬性
└─ 例: 姓名、郵箱、年齡
2. 關聯式資料庫範例
-- users表
users
┌────┬────────┬──────────────────┬─────┐
│ id │ name │ email │ age │
├────┼────────┼──────────────────┼─────┤
│ 1 │ 王小明 │ wang@mail.com │ 25 │
│ 2 │ 李小華 │ lee@mail.com │ 30 │
│ 3 │ 張大衛 │ chang@mail.com │ 28 │
└────┴────────┴──────────────────┴─────┘
-- orders表
orders
┌────┬─────────┬─────────────┬───────┐
│ id │ user_id │ product │ price │
├────┼─────────┼─────────────┼───────┤
│ 1 │ 1 │ 筆記型電腦 │ 1500 │
│ 2 │ 1 │ 滑鼠 │ 30 │
│ 3 │ 2 │ 鍵盤 │ 80 │
└ ────┴─────────┴─────────────┴───────┘
↑
└─ 外鍵: 引用users表的id
3. CRUD操作
CRUD是資料庫的4種基本操作:
C - Create (建立): 新增資料
R - Read (讀取): 查詢資料
U - Update (更新): 修改現有資料
D - Delete (刪除): 刪除資料
💡 實際範例
使用SQL進行CRUD
-- CREATE (建立): 建立表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- CREATE (建立): 新增資料
INSERT INTO users (name, email, age)
VALUES ('王小明', 'wang@mail.com', 25);
INSERT INTO users (name, email, age)
VALUES
('李小華', 'lee@mail.com', 30),
('張大衛', 'chang@mail.com', 28);
-- READ (讀取): 查詢所有使用者
SELECT * FROM users;
-- READ (讀取): 條件查詢
SELECT name, email FROM users
WHERE age >= 28;
-- READ (讀取): 排序查詢
SELECT * FROM users
ORDER BY age DESC;
-- READ (讀取): 搜尋
SELECT * FROM users
WHERE name LIKE '王%';
-- UPDATE (更新): 修改資料
UPDATE users
SET age = 26
WHERE name = '王小明';
-- UPDATE (更新): 修改多個欄位
UPDATE users
SET email = 'new@mail.com', age = 31
WHERE id = 2;
-- DELETE (刪除): 刪除資料
DELETE FROM users
WHERE id = 3;
-- DELETE (刪除): 條件刪除
DELETE FROM users
WHERE age < 20;
Node.js中使用資料庫
const mysql = require('mysql2/promise');
// 資料庫連接
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
waitForConnections: true,
connectionLimit: 10
});
// CREATE - 新增使用者
async function createUser(name, email, age) {
const [result] = await pool.execute(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
[name, email, age]
);
console.log('建立的ID:', result.insertId);
return result.insertId;
}
// READ - 取得所有使用者
async function getAllUsers() {
const [rows] = await pool.execute('SELECT * FROM users');
return rows;
}
// READ - 取得特定使用者
async function getUserById(id) {
const [rows] = await pool.execute(
'SELECT * FROM users WHERE id = ?',
[id]
);
return rows[0];
}
// UPDATE - 更新使用者資訊
async function updateUser(id, name, email, age) {
const [result] = await pool.execute(
'UPDATE users SET name = ?, email = ?, age = ? WHERE id = ?',
[name, email, age, id]
);
console.log('更新的行數:', result.affectedRows);
return result.affectedRows;
}
// DELETE - 刪除使用者
async function deleteUser(id) {
const [result] = await pool.execute(
'DELETE FROM users WHERE id = ?',
[id]
);
console.log('刪除的行數:', result.affectedRows);
return result.affectedRows;
}
// 使用範例
async function main() {
try {
// 建立
const userId = await createUser('王小明', 'wang@mail.com', 25);
// 查詢
const users = await getAllUsers();
console.log('所有使用者:', users);
// 查詢特定使用者
const user = await getUserById(userId);
console.log('特定使用者:', user);
// 更新
await updateUser(userId, '王小明', 'new@mail.com', 26);
// 刪除
await deleteUser(userId);
} catch (error) {
console.error('錯誤:', error);
}
}
main();
ORM使用 (Sequelize)
const { Sequelize, DataTypes } = require('sequelize');
// 資料庫連接
const sequelize = new Sequelize('myapp', 'root', 'password', {
host: 'localhost',
dialect: 'mysql'
});
// 模型定義 (表結構)
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true
},
age: {
type: DataTypes.INTEGER
}
});
// CRUD操作 (無需SQL,只用JavaScript!)
async function ormExample() {
// CREATE - 建立
const user = await User.create({
name: '王小明',
email: 'wang@mail.com',
age: 25
});
console.log('建立:', user.toJSON());
// READ - 查詢
const allUsers = await User.findAll();
console.log('所有使用者:', allUsers);
// READ - 條件查詢
const youngUsers = await User.findAll({
where: { age: { [Sequelize.Op.gte]: 20 } },
order: [['age', 'DESC']]
});
// READ - 查詢單個
const oneUser = await User.findOne({
where: { email: 'wang@mail.com' }
});
// UPDATE - 更新
await User.update(
{ age: 26 },
{ where: { name: '王小明' } }
);
// DELETE - 刪除
await User.destroy({
where: { id: 1 }
});
}
關係設定 (JOIN)
// 使用者和訂單的關係設定
const User = sequelize.define('User', {
name: DataTypes.STRING,
email: DataTypes.STRING
});
const Order = sequelize.define('Order', {
product: DataTypes.STRING,
price: DataTypes.DECIMAL(10, 2)
});
// 關係定義: 一個使用者可以有多個訂單
User.hasMany(Order);
Order.belongsTo(User);
// JOIN查詢
async function getUserWithOrders(userId) {
const userWithOrders = await User.findOne({
where: { id: userId },
include: Order // JOIN
});
console.log(userWithOrders.toJSON());
// {
// id: 1,
// name: '王小明',
// email: 'wang@mail.com',
// Orders: [
// { product: '筆記型電腦', price: 1500 },
// { product: '滑鼠', price: 30 }
// ]
// }
}
🤔 常見問題
Q1. 為什麼使用資料庫?
A: 比檔案系統有很多優勢:
❌ 檔案系統 (例: users.txt)
├─ 可能資料重複
├─ 並行存取問題
├─ 備份/恢復困難
├─ 安全漏洞
└─ 搜尋慢
✅ 資料庫
├─ 保證資料完整性
├─ 並行控制 (多使用者)
├─ 自動備份/恢復
├─ 存取權限管理
├─ 快速搜尋 (索引)
└─ 交易支援
Q2. 應該選擇哪個資料庫?
A: 取決於專案需求:
// 關聯式資料庫 (SQL)
MySQL / PostgreSQL / SQLite
├─ 優點: 精確的資料結構、交易
├─ 缺點: 靈活性低、可擴展性有限
└─ 適用: 金融、電子商務、使用者管理
// 非關聯式資料庫 (NoSQL)
MongoDB / Redis / Cassandra
├─ 優點: 靈活的模式、水平擴展
├─ 缺點: 複雜關係處理困難
└─ 適用: 社群媒體、即時分析、快取
Q3. 什麼是索引(Index)?
A: 加速資料檢索的資料結構:
-- 沒有索引
SELECT * FROM users WHERE email = 'test@mail.com';
-- → 檢查所有100萬行 (慢)
-- 建立索引
CREATE INDEX idx_email ON users(email);
-- 有索引
SELECT * FROM users WHERE email = 'test@mail.com';
-- → 透過索引直接查找 (快!)
-- 缺點: 資料插入/更新時索引也要更新 (寫入變慢)
類比: 就像書的目錄或索引,可以快速找到想要的內容。