celld中文文档v0.6.2
GitHub ↗
服务 / 参考文档

D1

D1 是通过绑定供 Worker 访问的 SQL 数据库。在 celld 中,每个数据库都有独立的 SQLite 文件,并位于一个单元内。API 的详细说明请参阅 Cloudflare D1 文档。

示例#

D1 示例 使用 D1 数据库实现留言簿。

wrangler.jsonc

json
{
  "name": "d1",
  "main": "index.js",
  "compatibility_date": "2026-01-01",
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "guestbook",
      "database_id": "00000000-0000-0000-0000-000000000000"
    }
  ]
}

index.js

javascript
const SCHEMA = `
CREATE TABLE IF NOT EXISTS entries (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  message TEXT NOT NULL,
  at INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS entries_at ON entries (at DESC);
`;

export default {
  async fetch(request, env) {
    await env.DB.exec(SCHEMA);
    const url = new URL(request.url);

    if (request.method === "POST") {
      const { name, message } = await request.json();
      const written = await env.DB
        .prepare("INSERT INTO entries (name, message, at) VALUES (?, ?, ?)")
        .bind(name, message, Date.now())
        .run();
      return Response.json({
        id: written.meta.last_row_id,
        changes: written.meta.changes,
      }, { status: 201 });
    }

    const count = await env.DB
      .prepare("SELECT count(*) AS n FROM entries")
      .first("n");
    if (url.pathname === "/count") return Response.json({ count });

    const { results } = await env.DB
      .prepare(
        "SELECT id, name, message, at FROM entries ORDER BY at DESC LIMIT ?",
      )
      .bind(20)
      .all();
    return Response.json({ count, entries: results });
  },
};

API#

  • prepare(sql) 返回一条预处理语句;bind(...values) 返回携带这些值的新语句。
  • all() 返回 success、由行对象组成的 results 数组以及 meta。run() 是同一方法的另一个名称。
  • first() 返回第一行或 null;first(column) 返回该行中的某一列。
  • raw() 以数组形式返回各行;raw({ columnNames: true }) 会将列名放在第一个数组中。
  • batch(statements) 在一个事务中执行多条预处理语句,并为每条语句返回一个结果。
  • exec(sql) 执行一条或多条不带参数的语句,例如建表语句。

配置与限制#

d1_databases 配置项包含 binding、database_name 和 database_id。celld 使用 database_id 作为数据库标识;未提供 ID 时则使用 database_name。两个 Worker 使用同一个标识时,会访问同一个数据库。celld 在首次使用时创建数据库,因此名称拼写错误会打开一个空数据库,而不会报错。

bind() 会检查每个值。数字和字符串可直接使用,布尔值转换为 1 或 0,ArrayBuffer、类型化数组或由字节数值组成的数组转换为 BLOB。其他值会触发 D1_TYPE_ERROR。celld 支持绑定位置参数 ? 和 ?NNN。

celld 执行以下 D1 限制:语句最多 100,000 字节,绑定参数最多 100 个,每张表最多 100 列,字符串、BLOB 或单行最多 2,200,000 字节。

预处理语句中如果包含第二条语句,会报错 A prepared SQL statement must contain only one statement.(SQL 预处理语句只能包含一条语句)。需要执行多条语句时,请使用 exec() 或 batch()。两者都会在一个事务内执行,因此任何失败都会回滚整次调用。

每条语句都会发送到拥有该数据库单元的节点,因此每次调用需要一次单元分发。将相关语句合并到一个 batch() 中,整个批次只需要一次分发。100,000 行的结果上限不适用于 first()。已确认的写入在拥有者节点丢失后仍然保留。

withSession() 始终选择主库。getBookmark() 返回 celld:primary,meta.served_by_primary 始终为 true,meta.served_by_region 始终为 local。

应用 SQL 不能使用 BEGIN、COMMIT、ROLLBACK、SAVEPOINT、ATTACH、DETACH、VACUUM、load_extension(),也不能使用临时表、索引、触发器或视图。celld 允许 fts5 和 fts5vocab 虚拟表,并接受 D1 SQL 语句参考中列出的 PRAGMA。

celld d1 execute 和 celld d1 migrations apply 通过正在运行的节点从命令行执行 SQL。

与 Cloudflare 的差异#

  • 绑定返回的结果最多包含 100,000 行或 32 MiB 数据。
  • 如果 SQLite 的 TEXT 值不是有效的 UTF-8,会像 workerd 一样使用替换字符 U+FFFD 解码,存储的原始字节保持不变。任意字节数据应存储为 BLOB。
  • 每个数据库只有一个写入者。增加数据库数量可以提高写入容量。
  • celld 没有只读副本。withSession() 始终选择主库,getBookmark() 返回 celld:primary。
  • 只读语句的 last_row_id 和 changes 均为 0。Cloudflare 则返回同一连接上上一次写入留下的值。
  • prepare() 只能接受一条语句。
  • exec() 按语句计数;Cloudflare 按输入行计数。
  • dump() 会抛出异常。数据库就是运维者自有存储桶中的 SQLite 文件。
  • 应用 SQL 不能使用 BEGIN、SAVEPOINT、ATTACH、VACUUM、load_extension() 或临时表。
  • celld 没有 D1 REST API,也没有 Time Travel。执行 SQL 和迁移请使用 celld d1。

Cloudflare 兼容性页面列出了运行时 API 和不支持的服务。

celld v0.6.2 · 简体中文文档
产品名、API、命令与示例代码保留原始写法。

输入关键词,搜索 20 篇中文文档。

支持中文术语、API 与环境变量 · Esc 关闭