Drizzle ORM上手指南:在Next.js中优雅地操作PostgreSQL

前言

在现代 Web 开发中,Next.js 配合 PostgreSQL 数据库已经成为了构建全栈应用的黄金搭档。而 Drizzle ORM 凭借其"无头"、类型安全且接近原生 SQL 的特性,正迅速成为开发者心中的新宠。

本文将带你从零开始,掌握如何在 Next.js 项目中配置 Drizzle,并熟练进行增删改查操作。


🏗️ 第一步:构建数据库连接单例

在开始写业务代码之前,我们需要建立一个数据库连接。在 Next.js 的开发环境中,由于热更新机制,如果每次请求都新建连接,很容易导致连接数耗尽。因此,我们需要使用全局单例模式 来管理 db 实例。

文件路径: src/db/index.ts

typescript 复制代码
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema'; // 引入你的表结构定义

// 1. 获取连接字符串
const connectionString = process.env.DATABASE_URL!;

// 2. 创建 postgres 客户端
// 注意:在生产环境建议使用连接池配置,开发环境这样写即可
const client = postgres(connectionString);

// 3. 导出 db 实例
// 这个 `db` 对象就是我们在 API 或组件中用来操作数据库的核心工具
export const db = drizzle(client, { schema });

💡 核心提示: 这个 db 对象封装了连接池和 SQL 构建器。只要在任何文件中 import { db } from '@/db',你就拥有了操作数据库的能力。


📚 第二步:掌握核心增删改查

Drizzle 的语法设计哲学是 "像写 SQL 一样写 TypeScript"。下面我们将通过具体的代码示例,解析最常用的四种操作。

1. 增:插入数据

对应 SQL:INSERT INTO users (name, email) VALUES (...) RETURNING *;

使用 .values() 传入数据对象,配合 .returning() 可以直接拿到插入后的完整数据(包含自增 ID)。

typescript 复制代码
import { db } from '@/db';
import { users } from '@/db/schema';

async function createUser() {
  const newUser = await db.insert(users).values({
    name: "Iron Man",
    email: "ironman@avengers.com"
  }).returning();

  console.log("插入成功:", newUser[0]);
}
2. 删:删除数据

对应 SQL:DELETE FROM users WHERE id = 1;

删除操作必须配合 .where() 使用,否则会导致全表数据被清空(删库跑路警告⚠️)。我们需要引入 eq 函数来构建等值条件。

typescript 复制代码
import { eq } from 'drizzle-orm';

async function deleteUser(userId: number) {
  await db.delete(users).where(eq(users.id, userId));
  console.log("删除成功");
}
3. 改:更新数据

对应 SQL:UPDATE users SET name = 'Captain America' WHERE id = 1;

使用 .set() 指定要修改的字段,同样需要配合 .where() 定位数据。

typescript 复制代码
import { eq } from 'drizzle-orm';

async function updateUser(userId: number) {
  await db.update(users)
    .set({ name: "Captain America" })
    .where(eq(users.id, userId));
    
  console.log("更新成功");
}
4. 查:查询数据

这是最灵活的部分,Drizzle 提供了链式调用来构建复杂的查询语句。

基础查询:

typescript 复制代码
// SELECT * FROM users;
const allUsers = await db.select().from(users);

条件查询:

引入 eq (等于), gt (大于), like (模糊) 等辅助函数。

typescript 复制代码
import { eq, gt, and, like } from 'drizzle-orm';

// SELECT * FROM users WHERE id = 1;
const user = await db.select().from(users).where(eq(users.id, 1));

// 复杂条件:SELECT * FROM users WHERE age > 18 AND name LIKE '%Stark%';
const adults = await db.select()
  .from(users)
  .where(and(gt(users.age, 18), like(users.name, '%Stark%')));

指定字段查询:

typescript 复制代码
// SELECT name, email FROM users;
const names = await db.select({
  name: users.name,
  email: users.email
}).from(users);

🔗 第三步:进阶关联查询

Drizzle 最强大的地方在于类型安全的关联查询。假设你有 users 表和 posts 表,想要查出用户及其文章,可以使用 .leftJoin()

typescript 复制代码
// SELECT * FROM users LEFT JOIN posts ON users.id = posts.userId;
const result = await db.select()
  .from(users)
  .leftJoin(posts, eq(users.id, posts.userId));

// result 的类型会被自动推断为:
// { users: User, posts: Post | null }[]

🛠️ 第四步:Drizzle Kit 命令行工具

除了代码层面的操作,你还需要掌握 Drizzle 的命令行工具来管理数据库结构。

命令 作用 对应 SQL 概念
npx drizzle-kit generate 扫描 schema.ts,生成迁移文件 生成 CREATE TABLE... 等 SQL 脚本
npx drizzle-kit migrate 执行迁移文件,同步到数据库 执行 SQL 脚本
npx drizzle-kit studio 启动可视化界面 类似 pgAdmin 的轻量版

📌 总结

学习 Drizzle 其实就是掌握以下三件事:

  1. 来源 :如何从 src/db/index.ts 导出 db 实例。
  2. 语法db.select(), db.insert(), db.update(), db.delete() 配合 .where().values()
  3. 工具 :使用 drizzle-kit 同步数据库结构。
相关推荐
techdashen15 小时前
用 Rust 写生产级服务要踩多少坑——Cloudflare 把答案做成了一个开源库
开发语言·rust·开源
码界奇点15 小时前
基于Python的微信公众号爬虫系统设计与实现
开发语言·爬虫·python·毕业设计·web·源代码管理
落雪寒窗-15 小时前
Python开发个人日常记录
开发语言·python
启山智软15 小时前
【 商城系统源码:Java与PHP的区别】
java·开发语言·php
练习时长两年半的程序员小胡15 小时前
Java程序员转大模型应用开发专题(一):核心基础概念
java·开发语言·transformer·自注意力
源图客15 小时前
PHP开发环境搭建
开发语言·php
Evand J15 小时前
MATLAB绘图函数介绍:plotmatrix绘图,附MATLAB例子
开发语言·matlab·绘图
比特 GOK15 小时前
Qt项目ui文件中新添加的控件在代码中不识别的问题解决
开发语言·qt·ui
云天AI实战派15 小时前
Agent 全流程实战:用 Python 搭建技能路由智能体,落地小龙虾门店运营助手
开发语言·人工智能·python
rit843249916 小时前
基于遗传算法的电动汽车充电站选址优化:模型与MATLAB实现
开发语言·matlab