零度AI
高级20 分钟阅读

Claude Code 数据库操作

使用 Claude Code 操作 MySQL、PostgreSQL、MongoDB 等数据库,执行 SQL、管理数据

Claude Code数据库SQLMongoDBORM

数据库操作概述

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 时,务必验证生成的语句,避免潜在的安全风险和数据问题。