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 更纯粹地聚焦查询构建。试写两天再定。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。