在日常开发中,数据库操作占据了相当大的工作量——编写 SQL 查询、设计表结构、编写 ORM 模型代码、优化慢查询等等。Codex 作为 OpenAI 开源的 AI 编码 CLI 工具,不仅能帮你写业务逻辑代码,在数据库相关任务上同样表现出色。本文将深入探讨如何利用 Codex 高效完成数据库相关的开发工作,从 SQL 生成到模式迁移,再到性能优化,覆盖数据库开发的完整链路。
Codex 最直接的应用场景就是用自然语言描述需求,让它生成对应的 SQL 语句。无论是简单的 SELECT 还是复杂的多表 JOIN + 子查询,Codex 都能准确理解意图。
假设有一个电商数据库,包含 users(用户表)、orders(订单表)和 order_items(订单明细表),你想查询"2025 年消费总额超过 5000 元的前 20 名用户及其最近一笔订单详情"。
在终端中进入项目目录,直接与 Codex 对话:
> 帮我写一个 SQL 查询:查询 2025 年消费总额超过 5000 元的前 20 名用户, 以及他们各自最近一笔订单的订单号、金额和下单时间。 表结构如下: - users: id, name, email - orders: id, user_id, order_no, total_amount, created_at - order_items: id, order_id, product_name, quantity, price
Codex 会生成类似这样的 SQL:
WITH user_annual_spending AS (
SELECT
u.id,
u.name,
u.email,
SUM(o.total_amount) AS total_spent
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE o.created_at >= '2025-01-01 00:00:00'
AND o.created_at < '2026-01-01 00:00:00'
GROUP BY u.id, u.name, u.email
HAVING SUM(o.total_amount) > 5000
ORDER BY total_spent DESC
LIMIT 20
),
latest_order AS (
SELECT
o.user_id,
o.order_no,
o.total_amount,
o.created_at,
ROW_NUMBER() OVER (PARTITION BY o.user_id ORDER BY o.created_at DESC) AS rn
FROM orders o
WHERE o.user_id IN (SELECT id FROM user_annual_spending)
)
SELECT
us.name,
us.email,
us.total_spent,
lo.order_no AS latest_order_no,
lo.total_amount AS latest_order_amount,
lo.created_at AS latest_order_time
FROM user_annual_spending us
LEFT JOIN latest_order lo ON us.id = lo.user_id AND lo.rn = 1
ORDER BY us.total_spent DESC;
生成结果使用了 CTE(公用表表达式)和窗口函数,结构清晰、可读性强。你还可以进一步追问:
> 如果 users 表数据量在千万级别,这个查询有哪些优化点?帮我分析索引策略。
生产环境中经常遇到需要批量修复数据的情况。比如:"将所有 2024 年 6 月之前的待支付订单标记为已取消"。
> 写一条 UPDATE 语句,将 orders 表中 status='pending' 且 created_at 早于 '2024-06-01' 的订单状态改为 'cancelled', 同时更新 updated_at 为当前时间。要求先输出 SELECT 确认影响行数,再给出 UPDATE。
Codex 会生成安全的二段式脚本:
-- 第一步:确认影响范围
SELECT COUNT(*) AS affected_rows
FROM orders
WHERE status = 'pending'
AND created_at < '2024-06-01 00:00:00';
-- 第二步:执行更新
UPDATE orders
SET status = 'cancelled',
updated_at = NOW()
WHERE status = 'pending'
AND created_at < '2024-06-01 00:00:00';
Codex 可以根据业务需求直接生成建表 DDL 语句。在设计新功能模块时,这个能力特别实用。
> 设计一个"文章标签系统"的数据库表结构,需求如下: - 一篇文章可以有多个标签,一个标签下有多篇文章(多对多) - 标签需要支持层级关系(父标签和子标签) - 每篇文章需要记录标签关联的创建时间 - 标签名全局唯一,且需要软删除 - 使用 MySQL,InnoDB 引擎,utf8mb4 字符集
Codex 会输出完整的三表结构:
CREATE TABLE tags (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL COMMENT '标签名称',
parent_id BIGINT UNSIGNED DEFAULT NULL COMMENT '父标签ID,NULL表示顶级标签',
sort_order INT DEFAULT 0 COMMENT '排序权重',
deleted_at TIMESTAMP NULL DEFAULT NULL COMMENT '软删除时间',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_name (name),
KEY idx_parent_id (parent_id),
KEY idx_deleted_at (deleted_at),
CONSTRAINT fk_tags_parent FOREIGN KEY (parent_id)
REFERENCES tags(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='标签表';
CREATE TABLE article_tags (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
article_id BIGINT UNSIGNED NOT NULL COMMENT '文章ID',
tag_id BIGINT UNSIGNED NOT NULL COMMENT '标签ID',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '关联时间',
UNIQUE KEY uk_article_tag (article_id, tag_id),
KEY idx_tag_id (tag_id),
KEY idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文章标签关联表';
注意 Codex 自动添加了唯一约束防止重复关联、给外键列加了索引、使用了规范的注释,这些都是良好的工程实践。
如果你使用 Laravel 框架,可以让 Codex 直接将上述表结构转换为 Migration 文件:
> 将上面三个 MySQL 建表语句转换为 Laravel Migration, 文件名分别为 create_tags_table 和 create_article_tags_table
Codex 会生成对应的 PHP Migration 代码:
// database/migrations/xxxx_create_tags_table.php
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('name', 50)->comment('标签名称');
$table->unsignedBigInteger('parent_id')->nullable()->comment('父标签ID');
$table->integer('sort_order')->default(0)->comment('排序权重');
$table->softDeletes()->comment('软删除时间');
$table->timestamps();
$table->unique('name');
$table->index('parent_id');
$table->index('deleted_at');
$table->foreign('parent_id')
->references('id')->on('tags')
->onDelete('set null');
});
然后在 AGENTS.md 中配置好项目的数据库连接信息,Codex 甚至能帮你直接执行 php artisan migrate。
Codex 能根据建表语句或业务描述自动生成 Eloquent Model,包含完整的关联关系、访问器和查询作用域。
> 根据上面创建的 tags 和 article_tags 表,生成完整的 Eloquent Model, 包含 hasMany/hasOne 关联、parent/children 树形关联、 软删除 trait、以及按热度排序的 scope
生成的 Tag 模型类似:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Tag extends Model
{
use SoftDeletes;
protected $fillable = ['name', 'parent_id', 'sort_order'];
public function parent(): BelongsTo
{
return $this->belongsTo(Tag::class, 'parent_id');
}
public function children(): HasMany
{
return $this->hasMany(Tag::class, 'parent_id')->orderBy('sort_order');
}
public function articles(): BelongsToMany
{
return $this->belongsToMany(Article::class, 'article_tags')
->withPivot('created_at')
->withTimestamps();
}
public function scopePopular($query)
{
return $query->withCount('articles')->orderBy('articles_count', 'desc');
}
public function scopeRoot($query)
{
return $query->whereNull('parent_id');
}
}
同样,切换到 Go 项目时,Codex 可以生成 GORM 模型:
> 将上面三个 MySQL 表转为 Go 的 GORM 模型结构体
package models
import (
"time"
"gorm.io/gorm"
)
type Tag struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"type:varchar(50);uniqueIndex;not null;comment:标签名称" json:"name"`
ParentID *uint `gorm:"index;comment:父标签ID" json:"parent_id"`
SortOrder int `gorm:"default:0;comment:排序权重" json:"sort_order"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Parent *Tag `gorm:"foreignKey:ParentID" json:"parent,omitempty"`
Children []Tag `gorm:"foreignKey:ParentID" json:"children,omitempty"`
Articles []Article `gorm:"many2many:article_tags;" json:"-"`
}
type ArticleTag struct {
ID uint `gorm:"primaryKey" json:"id"`
ArticleID uint `gorm:"uniqueIndex:uk_article_tag;not null" json:"article_id"`
TagID uint `gorm:"uniqueIndex:uk_article_tag;not null;index" json:"tag_id"`
CreatedAt time.Time `json:"created_at"`
}
Codex 在数据库性能调优方面同样能发挥重要作用。你可以把 EXPLAIN 输出直接粘贴给 Codex,让它帮你分析并给出优化建议。
> 这个查询在 500 万条数据下执行超过 8 秒,帮我分析 EXPLAIN 输出并给出优化方案: EXPLAIN SELECT u.name, COUNT(o.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE o.created_at >= '2025-01-01' GROUP BY u.id HAVING order_count > 10 ORDER BY order_count DESC; EXPLAIN 输出: +----+-------------+-------+------+---------------+------+---------+------+---------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+---------+-------------+ | 1 | SIMPLE | o | ALL | idx_created_at| NULL | NULL | NULL | 5234872 | Using where | | 1 | SIMPLE | u | ALL | PRIMARY | NULL | NULL | NULL | 1023456 | Using where | +----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
Codex 会发现两个主要问题:(1)orders 表的 idx_created_at 索引未被使用;(2)LEFT JOIN 配合 WHERE 对右表过滤,实际退化成了 INNER JOIN。它会给出具体建议:
-- 修正后的查询(LEFT JOIN 改为 INNER JOIN) SELECT u.name, COUNT(o.id) as order_count FROM users u INNER JOIN orders o ON u.id = o.user_id WHERE o.created_at >= '2025-01-01' GROUP BY u.id HAVING order_count > 10 ORDER BY order_count DESC; -- 建议创建的复合索引 CREATE INDEX idx_orders_user_created ON orders(user_id, created_at);
更进一步,你可以让 Codex 分析慢查询日志:
> 从 MySQL 慢查询日志中提取了以下 TOP 10 慢查询(文件路径 slow.log), 帮我逐条分析并提供优化方案,然后生成一个 Markdown 格式的优化报告。
Codex 会通过文件读取功能分析日志内容,按查询类型分类(全表扫描、索引失效、回表过多等),输出结构化的优化报告。
Codex 的 exec 命令特别适合批量任务。比如为新模块一次性生成整套 CRUD 代码:
codex exec "根据 tags 表的建表 DDL(文件在 schema.sql 中),
生成完整的 RESTful API 控制器代码:
1. GET /api/tags - 分页列表,支持 name 模糊搜索和 parent_id 筛选
2. GET /api/tags/{id} - 详情,包含子标签和文章数量
3. POST /api/tags - 创建标签
4. PUT /api/tags/{id} - 更新标签
5. DELETE /api/tags/{id} - 软删除,如果有子标签则禁止删除
使用 Laravel 框架,请求验证用 FormRequest,资源响应用 API Resource"
Codex 还能帮你编写数据库之间数据迁移的 ETL 脚本:
> 我需要从旧系统的 MySQL 数据库迁移用户数据到新系统的 PostgreSQL。 写一个 Python 脚本,使用 SQLAlchemy 连接两个数据库, 对 users 表进行字段映射和数据类型转换, 支持断点续传(记录最后迁移的 ID), 并输出每分钟的迁移进度。
Codex 会生成包含批量处理、异常捕获和进度日志的完整脚本。
如果你已经为 Codex 配置了数据库 MCP 服务器(参见之前的 MCP 集成文章),更可以让 Codex 直接执行数据库操作:
> 查看当前数据库中所有表的大小(按数据量降序排列) > 找出没有设置 created_at 索引的所有表,生成 ALTER TABLE 语句 > 分析 users 表的数据分布:按注册月份统计用户数,输出为柱状图
AI 生成的 SQL 虽然多数情况下准确,但在生产环境执行前务必仔细审查。建议在 AGENTS.md 中添加规则:
## 数据库操作规则 - 任何涉及写操作(INSERT/UPDATE/DELETE)的 SQL 必须先输出预览版本,经我确认后再执行 - MySQL 环境 UPDATE 和 DELETE 必须包含 LIMIT 子句 - 生产环境禁止执行 DROP 或 TRUNCATE
Codex 不是数据库客户端,它需要你主动提供表结构信息。最佳实践是:
在项目 AGENTS.md 中列出核心表及其字段说明
对于复杂查询,在 schema.sql 文件中维护完整的建表 DDL
提问时附上相关表的 CREATE TABLE 语句片段
Codex 还是优秀的学习工具。遇到不熟悉的 SQL 语法时,直接问它:
> Oracle 的 CONNECT BY 和 SQL Server 的 CTE 递归查询有什么区别? 分别给出示例,查询一个部门层级树。 > 解释一下 MySQL 的覆盖索引(Covering Index)是什么, 为什么有时候 EXPLAIN 的 Extra 字段显示 Using index 但查询仍然很慢?
将 Codex 集成到你的数据库工具链中:
Codex 在数据库开发领域的能力远超简单的 SQL 补全——它能够理解业务语义、设计表结构、生成 ORM 模型、分析查询性能,甚至编写完整的数据迁移脚本。将 Codex 融入日常数据库工作流,可以显著减少手工编写 SQL 和模板代码的时间,让你更专注于数据建模和架构设计。
在实际使用中,关键是提供充分的上下文信息(表结构、业务需求)并建立安全的使用规范(先审阅后执行)。掌握这些技巧后,你会发现 Codex 不仅是应用层编码的得力助手,更是数据库开发的效率倍增器。