Knex.js 入门指南:用 JavaScript 写 SQL
Knex.js 是跨数据库的 SQL 查询构造器:链式 API 构建查询、防注入、支持 PostgreSQL/MySQL/SQLite。本文走完建库、增删改查全流程。
Knex 让 SQL 用 JS 链式书写:knex('users').where('age', '>', 18).select('name') 生成参数化查询——既保留 SQL 的表达能力与可控性,又自动防注入、跨数据库方言。它不隐藏 SQL,是"SQL 优先"团队的正确工具。
Knex 的定位
ORM 把数据库抽象成对象,Knex 只把 SQL 抽象成链式调用——表还是表、join 还是 join,你始终知道执行的 SQL 长什么样。换来的:零黑盒、跨方言、参数化防注入。
初始化与建表
npm install knex better-sqlite3
const knex = require('knex')({
client: 'better-sqlite3',
connection: { filename: './app.db' },
useNullAsDefault: true,
});
// 建表
await knex.schema.createTable('users', (table) => {
table.increments('id');
table.string('name').notNullable();
table.string('email').unique().notNullable();
table.integer('age');
table.timestamps(true, true);
});
插入数据
const [id] = await knex('users').insert({
name: '张三', email: 'zhang@example.com', age: 28,
});
// 批量
await knex('users').insert([
{ name: '李四', email: 'li@example.com', age: 32 },
{ name: '王五', email: 'wang@example.com', age: 25 },
]);
参数化是自动的——insert({ name: userInput }) 永远安全,不存在拼接 SQL 注入。
查询数据
// 全量
const users = await knex('users').select('*');
// 条件 + 排序 + 分页
const adults = await knex('users')
.where('age', '>=', 18)
.orderBy('age', 'desc')
.limit(10).offset(20);
// 聚合
const stats = await knex('users')
.avg('age as avg_age')
.count('id as total')
.first();
// join
const rows = await knex('users')
.join('posts', 'users.id', 'posts.user_id')
.select('users.name', 'posts.title');
where 支持对象简写({ name: '张三' })、操作符(where('age', '>', 18))、范围(whereBetween)、子查询——SQL 的表达力基本无损映射。
更新与删除
// 更新(务必带 where!)
const affected = await knex('users')
.where({ id: 1 })
.update({ age: 29 });
// 删除
await knex('users').where({ id: 1 }).del();
铁律:update/del 不带 where 就是全表操作——代码评审重点盯这一条。
事务
await knex.transaction(async (trx) => {
await trx('accounts').where({ id: 1 }).decrement('balance', 100);
await trx('accounts').where({ id: 2 }).increment('balance', 100);
// 抛错自动回滚,正常结束自动提交
});
用实际查询验证数据访问方案
Knex.js 入门指南的选择最终要落到查询次数、SQL 耗时与连接占用。应用接入观测云 APM 时,先核对 SDK 是否支持实际使用的数据库驱动,不能因为使用了某个 ORM 就假设全部查询自动可见。未覆盖的查询可手动插桩;PostgreSQL 等服务端数据库另配实例采集。SQL 和绑定参数上报前须脱敏,再按相同接口比较 N+1 查询与慢查询的变化。
接入文档:Node.js APM 接入 · PostgreSQL 采集 · 日志采集。
常见问题(FAQ)
Q:Knex 和 ORM 怎么选?
见本系列《Knex 和 Prisma 对比》。一句话:想掌控 SQL 选 Knex,想操作对象选 Prisma/Drizzle。
Q:生产环境数据库迁移怎么管理?
Knex 自带迁移系统:knex migrate:make xxx 生成迁移文件,knex migrate:latest 执行。迁移文件入版本库,CI/CD 流程中自动执行。
Q:Knex 还在维护吗?
维护中且稳定——它是"完成度高"的工具而非"停滞"。TypeScript 支持可用但类型推导有限(Kysely 在类型化方向走得更远)。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。