数据库

Nitro 提供了一个内置的轻量级 SQL 数据库层。

默认数据库连接已通过 SQLite 预配置,可在开发模式和任何兼容 Node.js 的生产部署中开箱即用。默认情况下,数据将存储在 .data/db.sqlite 中。

Read more in DB0 文档.

Important

数据库支持目前处于实验阶段。 请参阅 db0 issues 了解状态并报告错误。

数据库层默认不启用。启用实验性功能标志:

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  experimental: {
    database: true
  }
})

#使用

server.ts
import { defineHandler } from "nitro";
import { useDatabase } from "nitro/database";

export default defineHandler(async () => {
  const db = useDatabase();

  // Create users table
  await db.sql`DROP TABLE IF EXISTS users`;
  await db.sql`CREATE TABLE IF NOT EXISTS users ("id" TEXT PRIMARY KEY, "firstName" TEXT, "lastName" TEXT, "email" TEXT)`;

  // Add a new user
  const userId = String(Math.round(Math.random() * 10_000));
  await db.sql`INSERT INTO users VALUES (${userId}, 'John', 'Doe', '')`;

  // Query for users
  const { rows } = await db.sql`SELECT * FROM users WHERE id = ${userId}`;

  return {
    rows,
  };
});

#useDatabase

使用 useDatabase 获取数据库实例。它接受一个可选的连接名称(默认为 "default")。

import { useDatabase } from "nitro/database";

// 使用默认连接
const db = useDatabase();

// 使用命名连接
const usersDb = useDatabase("users");

数据库实例会在首次使用时延迟创建,并在后续使用相同连接名称调用时进行缓存。如果连接名称未配置,将抛出错误。

#db.sql

使用带标签的模板字面量和自动参数绑定执行 SQL 查询:

const db = useDatabase();

// 使用参数化值插入(防止 SQL 注入)
const id = "1001";
await db.sql`INSERT INTO users VALUES (${id}, 'John', 'Doe', '[email protected]')`;

// 使用参数查询
const { rows } = await db.sql`SELECT * FROM users WHERE id = ${id}`;

// 结果包含行、变更计数和最后插入的 ID
const result = await db.sql`INSERT INTO posts (title) VALUES (${"Hello"})`;
// result.rows, result.changes, result.lastInsertRowid

#db.exec

直接执行原始 SQL 字符串:

const db = useDatabase();

await db.exec("CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, name TEXT)");

#db.prepare

准备 SQL 语句以供重复执行:

const db = useDatabase();

const stmt = db.prepare("SELECT * FROM users WHERE id = ?");
const result = await stmt.bind("1001").all();

#配置

你可以使用 database 配置更改默认连接,或为任意受支持的数据库定义其他命名连接,并将数据库实例与任意受支持的 ORM集成。

每个连接都是一个包含 connector 名称和可选 options 对象的 DatabaseConnectionConfig。特定连接器的设置(例如 url、host 或 name)应放在 options 下,而不是连接配置的顶层。

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  database: {
    default: {
      connector: "sqlite",
      options: { name: "db" },
    },
    users: {
      connector: "postgresql",
      options: {
        url: "postgresql://username:password@hostname:port/database_name",
      },
    },
    analytics: {
      connector: "mysql2",
      options: {
        host: "localhost",
        port: 3306,
        user: "root",
        password: "password",
        database: "analytics",
      },
    },
  },
});

请参阅 db0 连接器文档,了解每个连接器接受的 options。

#开发数据库

使用 devDatabase 配置来仅在开发模式下覆盖数据库配置。这对于在开发期间使用本地 SQLite 数据库,同时在生产环境中使用不同的数据库非常有用。

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  database: {
    default: {
      connector: "postgresql",
      options: {
        url: "postgresql://username:password@hostname:port/database_name"
      }
    }
  },
  devDatabase: {
    default: {
      connector: "sqlite",
      options: { name: "dev-db" }
    }
  }
});

Note

在开发环境中,提供的 devDatabase 会完全替换 database 配置;连接不会按名称合并。请在 devDatabase 中包含开发期间所需的每个连接。

Tip

启用 experimental.database 且未提供 database 或 devDatabase 配置时,Nitro 会自动配置一个默认的 SQLite 连接。在开发模式下,数据会存储在相对于项目根目录的位置。在 Node.js 生产环境中,则使用默认的 SQLite 路径。

#连接器

Nitro 支持所有 db0 连接器。数据库配置中的 connector 字段接受以下任意值:

连接器描述
sqliteNode.js 内置 SQLite(node-sqlite 的别名)
node-sqliteNode.js 内置 SQLite
better-sqlite3better-sqlite3
sqlite3sqlite3
bun / bun-sqliteBun 内置 SQLite
libsql / libsql-nodelibSQL(Node.js)
libsql-http基于 HTTP 的 libSQL
libsql-web用于 Web 环境的 libSQL
libsql-core使用用户提供客户端的 libSQL
postgresqlPostgreSQL
mysql2MySQL
pglitePGlite(嵌入式 PostgreSQL)
planetscalePlanetScale 无服务器数据库
neonNeon 无服务器数据库
cloudflare-d1Cloudflare D1
cloudflare-hyperdrive-mysql使用 MySQL 的 Cloudflare Hyperdrive
cloudflare-hyperdrive-postgresql使用 PostgreSQL 的 Cloudflare Hyperdrive

#连接器依赖

某些连接器依赖第三方库(例如,postgresql 需要 pg)。

Nitro 会检测已配置连接所需的库,并提示安装缺失的库(在 CI 中会自动安装)。随后,已安装的库会通过其 lib 选项显式传递给连接器,以便打包器能够静态解析它们。