跳到主要内容

D1 数据库

Cloudflare D1 是一个基于 SQLite 的边缘数据库,专为 Cloudflare Workers 设计。它提供低延迟的数据库访问,非常适合构建全栈应用。

D1 简介

什么是 D1?

D1 是 Cloudflare 提供的无服务器 SQL 数据库,基于 SQLite 构建。它将数据库部署到边缘节点,让数据更接近用户。

D1 的特点

SQLite 兼容:使用熟悉的 SQL 语法,支持大多数 SQLite 功能。

边缘部署:数据库在边缘节点运行,延迟极低。

自动复制:数据自动复制到多个位置,保证高可用。

与 Workers 深度集成:直接在 Worker 中访问数据库。

免费额度

资源免费额度
存储空间5GB
读取行数500 万行/月
写入行数10 万行/月

快速开始

创建数据库

使用 Wrangler CLI 创建数据库:

# 创建数据库
npx wrangler d1 create my-database

输出会显示数据库 ID,保存这个 ID 用于配置。

配置绑定

wrangler.toml 中添加绑定:

[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-database-id"

创建表

创建 SQL 文件 schema.sql

CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT,
user_id INTEGER,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);

执行 SQL:

# 本地数据库
npx wrangler d1 execute my-database --local --file=./schema.sql

# 远程数据库
npx wrangler d1 execute my-database --remote --file=./schema.sql

在 Workers 中使用 D1

查询数据

export default {
async fetch(request, env, ctx) {
const result = await env.DB.prepare(
'SELECT * FROM users ORDER BY created_at DESC'
).all();

return Response.json(result.results);
},
};

参数化查询

export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const id = url.searchParams.get('id');

const result = await env.DB.prepare(
'SELECT * FROM users WHERE id = ?'
).bind(id).first();

if (!result) {
return new Response('Not Found', { status: 404 });
}

return Response.json(result);
},
};

插入数据

export default {
async fetch(request, env, ctx) {
const body = await request.json();

const result = await env.DB.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
).bind(body.name, body.email).run();

return Response.json({
id: result.meta.last_row_id,
success: result.success
});
},
};

更新数据

export default {
async fetch(request, env, ctx) {
const body = await request.json();

const result = await env.DB.prepare(
'UPDATE users SET name = ?, email = ? WHERE id = ?'
).bind(body.name, body.email, body.id).run();

return Response.json({
changes: result.meta.changes,
success: result.success
});
},
};

删除数据

export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const id = url.searchParams.get('id');

const result = await env.DB.prepare(
'DELETE FROM users WHERE id = ?'
).bind(id).run();

return Response.json({
success: result.success
});
},
};

批量操作

批量插入

export default {
async fetch(request, env, ctx) {
const users = await request.json();

const statements = users.map(user =>
env.DB.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
).bind(user.name, user.email)
);

const results = await env.DB.batch(statements);

return Response.json({
inserted: results.length
});
},
};

事务

D1 支持事务操作:

export default {
async fetch(request, env, ctx) {
const body = await request.json();

try {
const result = await env.DB.batch([
env.DB.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
.bind(body.name, body.email),
env.DB.prepare('INSERT INTO posts (title, user_id) VALUES (?, last_insert_rowid())')
.bind(body.firstPostTitle),
]);

return Response.json({ success: true });
} catch (error) {
return Response.json({ error: error.message }, { status: 500 });
}
},
};

使用 ORM

Drizzle ORM

Drizzle 是一个轻量级 TypeScript ORM,支持 D1:

npm install drizzle-orm drizzle-kit

配置 drizzle.config.ts

import { defineConfig } from 'drizzle-kit';

export default defineConfig({
schema: './src/schema.ts',
out: './drizzle',
dialect: 'sqlite',
driver: 'd1-http',
dbCredentials: {
accountId: 'your-account-id',
databaseId: 'your-database-id',
token: 'your-api-token',
},
});

定义 Schema:

import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';

export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull(),
email: text('email').notNull().unique(),
createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
});

使用 ORM:

import { drizzle } from 'drizzle-orm/d1';
import { users } from './schema';
import { eq } from 'drizzle-orm';

export default {
async fetch(request, env, ctx) {
const db = drizzle(env.DB);

const allUsers = await db.select().from(users);

const user = await db.select().from(users)
.where(eq(users.id, 1));

await db.insert(users).values({
name: 'John',
email: '[email protected]',
});

return Response.json(allUsers);
},
};

REST API 示例

构建完整的 REST API:

import { Hono } from 'hono';

type Bindings = {
DB: D1Database;
};

const app = new Hono<{ Bindings: Bindings }>();

// 获取所有用户
app.get('/api/users', async (c) => {
const result = await c.env.DB.prepare(
'SELECT * FROM users ORDER BY created_at DESC'
).all();
return c.json(result.results);
});

// 获取单个用户
app.get('/api/users/:id', async (c) => {
const id = c.req.param('id');
const result = await c.env.DB.prepare(
'SELECT * FROM users WHERE id = ?'
).bind(id).first();

if (!result) {
return c.json({ error: 'Not Found' }, 404);
}

return c.json(result);
});

// 创建用户
app.post('/api/users', async (c) => {
const body = await c.req.json();

const result = await c.env.DB.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
).bind(body.name, body.email).run();

return c.json({ id: result.meta.last_row_id }, 201);
});

// 更新用户
app.put('/api/users/:id', async (c) => {
const id = c.req.param('id');
const body = await c.req.json();

const result = await c.env.DB.prepare(
'UPDATE users SET name = ?, email = ? WHERE id = ?'
).bind(body.name, body.email, id).run();

return c.json({ changes: result.meta.changes });
});

// 删除用户
app.delete('/api/users/:id', async (c) => {
const id = c.req.param('id');

await c.env.DB.prepare(
'DELETE FROM users WHERE id = ?'
).bind(id).run();

return c.json({ success: true });
});

export default app;

数据库管理

查看数据库列表

npx wrangler d1 list

执行单条 SQL

npx wrangler d1 execute my-database --command "SELECT * FROM users"

导出数据

npx wrangler d1 export my-database --output=backup.sql

查看数据库信息

npx wrangler d1 info my-database

常见问题

D1 和传统数据库有什么区别?

D1 是边缘数据库,数据存储在边缘节点,延迟更低。但它有存储和写入限制,适合中小型应用。

如何处理数据库迁移?

使用 Drizzle Kit 或手动管理 SQL 迁移文件:

npx drizzle-kit generate:sqlite
npx drizzle-kit push:sqlite

支持哪些 SQLite 功能?

D1 支持大多数 SQLite 功能,但不支持:

  • ATTACH DATABASE
  • PRAGMA 语句(部分)
  • 用户定义函数

参考链接

下一步

完成 D1 学习后,接下来学习 KV 存储,了解如何使用键值存储。