示例说明
Drizzle 的表定义是唯一事实源:列类型即 TypeScript 类型,select 里挑了哪些列结果就长什么样,漏列多列都过不了编译。联表条件用 eq 这类运算符函数表达,值走参数化通道而非字符串拼接。相比手写 SQL,重构表结构时所有受影响查询会被编译器逐个点名。
技术要点
- select 形状直接决定行的类型
- 运算符函数保证条件参数化
- 表定义与数据库结构的同步迁移
代码解读
recentBigOrders 的 select 挑选三个列,返回数组的元素类型即由此推断;innerJoin 用 eq 匹配外键关系,where 组装大于等于条件,orderBy 与 limit 完成排序截断。查询结束后 pool.end 归还连接资源。
使用建议
列名映射让数据库 snake_case 与代码 camelCase 自然转换。复杂统计用 sql 模板嵌入原生片段但保持参数化。迁移文件要进版本库并评审。
代码示例
import { pgTable, serial, text, integer, timestamp } from 'drizzle-orm/pg-core';
import { drizzle } from 'drizzle-orm/node-postgres';
import { eq, gte, desc, and, sql } from 'drizzle-orm';
import { Pool } from 'pg';
const customers = pgTable('customers', {
id: serial('id').primaryKey(),
email: text('email').notNull(),
});
const orders = pgTable('orders', {
id: serial('id').primaryKey(),
customerId: integer('customer_id').notNull(),
total: integer('total').notNull(),
createdAt: timestamp('created_at').defaultNow(),
});
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const db = drizzle(pool);
async function recentBigOrders(minTotal: number) {
const rows = await db
.select({
orderId: orders.id,
email: customers.email,
total: orders.total,
})
.from(orders)
.innerJoin(customers, eq(orders.customerId, customers.id))
.where(and(gte(orders.total, minTotal)))
.orderBy(desc(orders.createdAt))
.limit(50);
return rows;
}
const qualified = await recentBigOrders(1000);
console.log('rows typed:', qualified[0]?.email.length ?? 0);
await pool.end();