一、数据库基础概念
数据库是结构化存储和管理数据的系统。前端工程师需要掌握数据库操作以更好地理解全栈架构、调试接口问题以及编写简单的后端服务。
关系型 vs 非关系型
| 特性 | 关系型(MySQL、PostgreSQL) | 非关系型(MongoDB、Redis) |
|---|
| 数据模型 | 表(Table)、行(Row)、列(Column) | 文档(Document)、集合(Collection) |
| 模式 | 固定 Schema,需预先定义 | 动态 Schema,灵活 |
| 关联 | 外键 + JOIN | 嵌入或引用 |
| 事务 | 支持 ACID | 基础支持 |
| 适用场景 | 强一致性、复杂查询 | 灵活数据结构、高并发 |
二、MySQL 基础操作
连接与数据库
1 2 3 4 5 6 7 8 9 10 11
| mysql -u root -p
SHOW DATABASES;
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE myapp;
|
表操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, age INT DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
DESCRIBE users;
ALTER TABLE users ADD COLUMN phone VARCHAR(20); ALTER TABLE users DROP COLUMN phone; ALTER TABLE users MODIFY COLUMN age TINYINT;
DROP TABLE users;
|
增删改查(CRUD)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@example.com', 25); INSERT INTO users (name, email, age) VALUES ('Bob', 'bob@example.com', 30), ('Charlie', 'charlie@example.com', 28);
SELECT * FROM users; SELECT name, email FROM users; SELECT * FROM users WHERE age > 25; SELECT * FROM users WHERE name LIKE 'A%'; SELECT * FROM users ORDER BY age DESC LIMIT 10;
SELECT COUNT(*) FROM users; SELECT AVG(age) FROM users; SELECT age, COUNT(*) FROM users GROUP BY age;
UPDATE users SET age = 26 WHERE name = 'Alice';
DELETE FROM users WHERE id = 3;
|
联表查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| CREATE TABLE orders ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, product VARCHAR(100), amount DECIMAL(10, 2), FOREIGN KEY (user_id) REFERENCES users(id) );
SELECT u.name, o.product, o.amount FROM users u INNER JOIN orders o ON u.id = o.user_id;
SELECT u.name, o.product FROM users u LEFT JOIN orders o ON u.id = o.user_id;
SELECT u.name, COUNT(o.id) AS order_count, SUM(o.amount) AS total FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id;
|
索引
1 2 3 4 5 6 7 8
| CREATE INDEX idx_email ON users(email);
CREATE INDEX idx_name_age ON users(name, age);
SHOW INDEX FROM users;
|
三、MongoDB 基础操作
连接与数据库
1 2 3 4 5 6 7 8
| mongosh
show dbs;
use myapp;
|
集合操作
1 2 3 4 5
| db.createCollection('users');
show collections;
|
增删改查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| db.users.insertOne({ name: 'Alice', email: 'alice@example.com', age: 25 }); db.users.insertMany([ { name: 'Bob', email: 'bob@example.com', age: 30 }, { name: 'Charlie', email: 'charlie@example.com', age: 28 }, ]);
db.users.find(); db.users.find({ age: { $gt: 25 } }); db.users.find({}, { name: 1, email: 1 }); db.users.find({ name: /^A/ }); db.users.find().sort({ age: -1 }).limit(10);
db.users.aggregate([ { $group: { _id: '$age', count: { $sum: 1 } } }, ]);
db.users.updateOne( { name: 'Alice' }, { $set: { age: 26 } } ); db.users.updateMany( { age: { $lt: 20 } }, { $set: { status: 'minor' } } );
db.users.deleteOne({ name: 'Charlie' }); db.users.deleteMany({ age: { $lt: 18 } });
|
索引
1 2 3
| db.users.createIndex({ email: 1 }); db.users.createIndex({ name: 1, age: -1 }); db.users.getIndexes();
|
关联查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
db.orders.insertOne({ userId: ObjectId('...'), product: 'Widget', amount: 99.9 });
db.users.aggregate([ { $lookup: { from: 'orders', localField: '_id', foreignField: 'userId', as: 'orders', }, }, ]);
|
四、Node.js 操作 MySQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const mysql = require('mysql2/promise');
async function main() { const conn = await mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'myapp', });
const [rows] = await conn.execute('SELECT * FROM users WHERE age > ?', [25]); console.log(rows);
const [result] = await conn.execute( 'INSERT INTO users (name, email, age) VALUES (?, ?, ?)', ['David', 'david@example.com', 22] ); console.log('Insert ID:', result.insertId);
await conn.end(); }
|
使用连接池:
1 2 3 4 5 6 7 8 9
| const pool = mysql.createPool({ host: 'localhost', user: 'root', database: 'myapp', waitForConnections: true, connectionLimit: 10, });
const [rows] = await pool.execute('SELECT * FROM users');
|
五、Node.js 操作 MongoDB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/myapp');
const userSchema = new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, unique: true }, age: { type: Number, default: 0 }, createdAt: { type: Date, default: Date.now }, });
const User = mongoose.model('User', userSchema);
const user = await User.create({ name: 'Alice', email: 'alice@example.com', age: 25 }); const users = await User.find({ age: { $gt: 20 } }).sort({ age: -1 }).limit(10); const updated = await User.findByIdAndUpdate(user._id, { age: 26 }, { new: true }); await User.findByIdAndDelete(user._id);
|
六、Redis 基础
Redis 是基于内存的键值数据库,常用于缓存和会话管理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| redis-cli
SET name "Alice" GET name
SET token "abc123" EX 3600 TTL token
LPUSH queue task1 RPOP queue
HSET user:1 name "Alice" age 25 HGET user:1 name HGETALL user:1
|
1 2 3 4 5 6
| const Redis = require('ioredis'); const redis = new Redis();
await redis.set('key', 'value', 'EX', 60); const val = await redis.get('key');
|
七、常见问题
Q1: SQL 注入是什么
1 2 3 4 5 6
| const sql = `SELECT * FROM users WHERE name = '${userInput}'`;
conn.execute('SELECT * FROM users WHERE name = ?', [userInput]);
|
Q2: N + 1 查询问题
1 2 3 4 5 6 7
| const users = await User.find(); for (const user of users) { const orders = await Order.find({ userId: user.id }); }
|
Q3: 如何选择 MySQL 和 MongoDB
- 数据结构固定、需要复杂 JOIN、强一致性 → MySQL
- 数据结构频繁变化、高并发写入、快速迭代 → MongoDB
- 缓存、会话、计数器 → Redis
八、推荐学习路径
- 掌握 SQL CRUD 和基础查询(WHERE、ORDER BY、LIMIT)
- 学习 JOIN 和聚合
- 理解索引原理和 EXPLAIN 分析慢查询
- 对比学习 MongoDB 的 CRUD 和聚合管道
- 在 Node.js 中操作数据库,注意 SQL 注入防范