Kysely 入门:类型安全的 SQL 查询构造器

Kysely 是 TypeScript 优先的 SQL 查询构造器:写 SQL 风格的查询同时获得完整类型推导。本文以 SQLite 为例走完建表、增删改查与事务。

最佳实践
事件循环与异步任务流转插画

Kysely 的定位是"类型安全的 Knex":查询 API 贴近 SQL,但表结构定义为 TS 类型后,字段名拼错、类型不匹配全部编译期报错。选型一句话:想要 SQL 的透明可控 + TypeScript 的安全网,Kysely 是当前最优解。

为什么是 Kysely

Knex 给了 SQL 控制但类型靠猜,Prisma 给了类型但隐藏 SQL——Kysely 站在中间:你写的还是 SQL 思维的查询,但每一列、每个 join 结果都有精确类型。纯 TS 实现无引擎依赖,冷启动快、Serverless 友好。

初始化

npm install kysely better-sqlite3
import { Kysely, Generated } from 'kysely';
import SQLite from 'better-sqlite3';
import { SqliteDialect } from 'kysely';

// 表结构即类型定义
interface Database {
  users: {
    id: Generated<number>;
    name: string;
    email: string;
    age: number | null;
    created_at: Generated<Date>;
  };
}

const db = new Kysely<Database>({
  dialect: new SqliteDialect({ database: new SQLite('./app.db') }),
});

// 建表
await db.schema
  .createTable('users')
  .addColumn('id', 'integer', (c) => c.primaryKey())
  .addColumn('name', 'text', (c) => c.notNull())
  .addColumn('email', 'text', (c) => c.notNull().unique())
  .addColumn('age', 'integer')
  .addColumn('created_at', 'datetime', (c) => c.defaultTo(new Date()))
  .execute();

增删改查

// 插入
const newUser = await db
  .insertInto('users')
  .values({ name: '张三', email: 'zhang@example.com', age: 28 })
  .returning(['id', 'created_at'])
  .executeTakeFirstOrThrow();

// 查询——字段名写错直接编译报错
const adults = await db
  .selectFrom('users')
  .select(['id', 'name', 'age'])
  .where('age', '>=', 18)
  .orderBy('age', 'desc')
  .limit(10)
  .execute();

// 更新
await db.updateTable('users')
  .set({ age: 29 })
  .where('id', '=', newUser.id)
  .execute();

// 删除
await db.deleteFrom('users').where('id', '=', 1).execute();

事务

await db.transaction().execute(async (trx) => {
  await trx.updateTable('accounts').set({ balance: sql`balance - 100` }).where('id', '=', 1).execute();
  await trx.updateTable('accounts').set({ balance: sql`balance + 100` }).where('id', '=', 2).execute();
});

trx 对象的类型与 db 一致——事务内的查询同样全类型检查。

进阶能力速览

  • 复杂表达式:expressionBuilder(eb)构建 CASE WHEN、子查询、函数调用,全部类型化;
  • 原生 SQL:sql<T>\...`` 模板,类型标注保留;
  • 迁移:内置 Migrator 跑 TS 迁移文件;
  • join 结果类型:多表 select 的返回类型自动推断为各表字段的并集——这是"类型安全查询构造器"的硬核体现。

用实际查询验证数据访问方案

Kysely 入门的选择最终要落到查询次数、SQL 耗时与连接占用。应用接入观测云 APM 时,先核对 SDK 是否支持实际使用的数据库驱动,不能因为使用了某个 ORM 就假设全部查询自动可见。未覆盖的查询可手动插桩;PostgreSQL 等服务端数据库另配实例采集。SQL 和绑定参数上报前须脱敏,再按相同接口比较 N+1 查询与慢查询的变化。

接入文档:Node.js APM 接入 · PostgreSQL 采集 · 日志采集。

常见问题(FAQ)

Q:Kysely 是 ORM 吗?

官方定位是查询构造器:无实体生命周期管理、无自动关联加载(join 自己写)。想要实体管理看 MikroORM;Kysely 服务的是"我知道我要什么 SQL"的场景。

Q:现有数据库怎么生成类型定义?

kysely-codegen 工具连接数据库反向生成 Database 接口——老项目接入零手写成本。

Q:Kysely 和 Drizzle 怎么选?

理念相近(TS 优先 + SQL 透明)。Drizzle 多了 Schema 即迁移的一体化与关系查询语法糖;Kysely 更纯粹地聚焦查询构建。试写两天再定。


参考文档

本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台