数据库操作概述
Claude Code 可以帮助你完成各种数据库操作,从建表到数据查询,从性能优化到数据迁移。本教程将介绍如何使用 Claude Code 高效操作数据库。
前置知识
本教程假设你已经熟悉基本的数据概念和至少一种编程语言。
SQL 数据库操作
MySQL 数据库
让 Claude Code 帮你创建表结构:
bash
帮我创建一个用户表,包含以下字段:
- id(自增主键)
- username(用户名,20字符,唯一)
- email(邮箱,100字符,唯一)
- password_hash(密码哈希)
- created_at(创建时间,默认当前时间)
- updated_at(更新时间)Claude Code 会生成类似下面的 SQL:
sql
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_username (username),
INDEX idx_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;PostgreSQL 数据库
创建表时使用 PostgreSQL 特有语法:
bash
帮我创建一个博客文章表,使用 PostgreSQL 语法,包含:
- id(UUID 主键)
- title(标题,不超过 200 字符)
- slug(URL 友好的别名,唯一)
- content(文章内容,TEXT 类型)
- author_id(关联用户 ID)
- published(是否发布,默认 false)
- created_at(创建时间)
- updated_at(更新时间)sql
CREATE TABLE posts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(200) NOT NULL,
slug VARCHAR(200) NOT NULL UNIQUE,
content TEXT,
author_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
published BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_posts_slug ON posts(slug);
CREATE INDEX idx_posts_author ON posts(author_id);
CREATE INDEX idx_posts_published ON posts(published) WHERE published = TRUE;NoSQL 数据库操作
MongoDB 操作
使用 Claude Code 操作 MongoDB:
bash
帮我创建一个用户管理的 JavaScript 模块,包含:
- 连接 MongoDB 的函数
- 创建用户的函数(密码加密)
- 根据邮箱查找用户的函数
- 更新用户信息的函数javascript
// db/users.js
import mongoose from "mongoose";
import bcrypt from "bcryptjs";
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3,
maxlength: 20,
},
email: {
type: String,
required: true,
unique: true,
lowercase: true,
trim: true,
},
password: {
type: String,
required: true,
minlength: 6,
},
avatar: String,
bio: String,
createdAt: {
type: Date,
default: Date.now,
},
updatedAt: {
type: Date,
default: Date.now,
},
});
// 密码加密中间件
userSchema.pre("save", async function (next) {
if (!this.isModified("password")) return next();
try {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
} catch (error) {
next(error);
}
});
// 密码验证方法
userSchema.methods.comparePassword = async function (candidatePassword) {
return bcrypt.compare(candidatePassword, this.password);
};
// 更新时间中间件
userSchema.pre("save", function (next) {
this.updatedAt = new Date();
next();
});
export const User = mongoose.model("User", userSchema);
// 连接数据库
export async function connectDB() {
if (mongoose.connection.readyState >= 1) return;
try {
await mongoose.connect(process.env.MONGODB_URI);
console.log("MongoDB connected successfully");
} catch (error) {
console.error("MongoDB connection error:", error);
throw error;
}
}
// 创建用户
export async function createUser(userData) {
const user = new User(userData);
return user.save();
}
// 根据邮箱查找用户
export async function findUserByEmail(email) {
return User.findOne({ email }).select("+password");
}
// 更新用户
export async function updateUser(userId, updates) {
return User.findByIdAndUpdate(userId, updates, { new: true });
}ORM 使用
Prisma ORM
使用 Claude Code 配合 Prisma:
bash
帮我创建一个完整的 Prisma Schema,包含:
- User 模型(用户)
- Post 模型(文章,关联 User)
- Comment 模型(评论,关联 Post 和 User)prisma
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
username String @unique @db.VarChar(20)
email String @unique @db.VarChar(100)
password String @map("password_hash")
avatar String?
bio String?
posts Post[]
comments Comment[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("users")
}
model Post {
id String @id @default(cuid())
title String @db.VarChar(200)
slug String @unique @db.VarChar(200)
content String? @db.Text
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
authorId String @map("author_id")
comments Comment[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@index([authorId])
@@index([published])
@@map("posts")
}
model Comment {
id String @id @default(cuid())
content String @db.Text
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
authorId String @map("author_id")
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
postId String @map("post_id")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@index([postId])
@@index([authorId])
@@map("comments")
}数据查询
复杂查询示例
bash
帮我写一个获取热门文章列表的查询,要求:
- 只查询已发布的文章
- 按评论数量排序
- 返回文章标题、作者名、评论数量、发布时间
- 限制返回 10 条sql
SELECT
p.id,
p.title,
p.slug,
p.created_at,
u.username AS author_name,
COUNT(c.id) AS comment_count
FROM posts p
INNER JOIN users u ON p.author_id = u.id
LEFT JOIN comments c ON p.id = c.post_id
WHERE p.published = TRUE
GROUP BY p.id, u.username
ORDER BY comment_count DESC, p.created_at DESC
LIMIT 10;MongoDB 聚合查询
javascript
// 获取热门文章
export async function getPopularPosts(limit = 10) {
return Post.aggregate([
{ $match: { published: true } },
{
$lookup: {
from: "users",
localField: "authorId",
foreignField: "_id",
as: "author",
},
},
{ $unwind: "$author" },
{
$lookup: {
from: "comments",
localField: "_id",
foreignField: "postId",
as: "comments",
},
},
{
$project: {
title: 1,
slug: 1,
createdAt: 1,
"author.username": 1,
commentCount: { $size: "$comments" },
},
},
{ $sort: { commentCount: -1, createdAt: -1 } },
{ $limit: limit },
]);
}数据迁移
使用 Claude Code 进行迁移
bash
帮我创建一个用户表的迁移脚本,添加新字段:
- is_verified(是否验证邮箱,布尔值,默认 false)
- verification_token(验证 Token)
- reset_password_token(重置密码 Token)
- reset_password_expires(重置密码过期时间)sql
-- migrations/20260404_add_user_verification.sql
-- 添加验证相关字段
ALTER TABLE users
ADD COLUMN is_verified BOOLEAN DEFAULT FALSE,
ADD COLUMN verification_token VARCHAR(64),
ADD COLUMN reset_password_token VARCHAR(64),
ADD COLUMN reset_password_expires TIMESTAMP;
-- 创建索引
CREATE INDEX idx_users_verification_token ON users(verification_token);
CREATE INDEX idx_users_reset_password_token ON users(reset_password_token);
-- 添加注释
COMMENT ON COLUMN users.is_verified IS '用户邮箱是否已验证';
COMMENT ON COLUMN users.verification_token IS '邮箱验证 Token';
COMMENT ON COLUMN users.reset_password_token IS '密码重置 Token';
COMMENT ON COLUMN users.reset_password_expires IS '密码重置 Token 过期时间';性能优化
索引优化
bash
帮我分析这个查询,并创建合适的索引:
SELECT * FROM orders
WHERE user_id = 123
AND status = 'completed'
ORDER BY created_at DESC
LIMIT 20;sql
-- 分析建议:创建复合索引
CREATE INDEX idx_orders_user_status_date ON orders(user_id, status, created_at DESC);
-- 验证索引效果
EXPLAIN ANALYZE
SELECT * FROM orders
WHERE user_id = 123
AND status = 'completed'
ORDER BY created_at DESC
LIMIT 20;最佳实践
1. 数据库连接池
javascript
// db/pool.js
import { Pool } from "pg";
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20, // 最大连接数
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
pool.on("error", (err) => {
console.error("Unexpected error on idle client", err);
});
export default pool;2. 事务处理
javascript
// 转账示例
export async function transferMoney(fromId, toId, amount) {
const client = await pool.connect();
try {
await client.query("BEGIN");
// 扣款
await client.query(
"UPDATE accounts SET balance = balance - $1 WHERE id = $2",
[amount, fromId]
);
// 加款
await client.query(
"UPDATE accounts SET balance = balance + $1 WHERE id = $2",
[amount, toId]
);
await client.query("COMMIT");
} catch (error) {
await client.query("ROLLBACK");
throw error;
} finally {
client.release();
}
}3. SQL 注入防护
javascript
// 使用参数化查询
export async function findUserByUsername(username) {
// 正确:使用参数化查询
return pool.query("SELECT * FROM users WHERE username = $1", [username]);
}安全提醒
永远不要将用户输入直接拼接到 SQL 语句中,这可能导致 SQL 注入攻击。
总结
通过 Claude Code,你可以高效完成各种数据库操作任务:
- 使用 Claude Code 生成 SQL 语句和表结构
- 创建数据库连接和 ORM 模型
- 编写复杂查询和聚合操作
- 进行数据迁移和性能优化
- 遵循安全最佳实践
记住,使用 Claude Code 生成 SQL 时,务必验证生成的语句,避免潜在的安全风险和数据问题。