Drizzle ORM 0.29.5 新特性实战指南:CTE 写操作、自定义迁移表与 SQLite Proxy 批量查询
Drizzle ORM 0.29.5 新特性实战指南CTE 写操作、自定义迁移表与 SQLite Proxy 批量查询【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-ormDrizzle ORM 0.29.5 是一个聚焦写操作与远程数据库能力的里程碑版本。本文围绕该版本 changelog 中的三大核心特性——WITH INSERT / UPDATE / DELETE写操作 CTE、迁移记录表的自定义表名与自定义 schema、SQLite Proxy 驱动的批量查询与关系查询支持——结合仓库源码与类型定义逐一给出可直接复制运行的配置示例、生成 SQL 对照与底层实现解析。读完本文你将掌握 Drizzle ORM 中 CTE 写操作的标准写法、迁移记录存储位置的精细化控制以及通过代理驱动对接自建 SQLite 服务的完整流程。一、用WITH语句组合写操作INSERT / UPDATE / DELETE在 0.29.5 之前Drizzle ORM 的$with()与.with()方法只支持 SELECT 查询中的公共表表达式CTE。本版本由 L-Mario564 贡献将 CTE 支持扩展到了 INSERT、UPDATE、DELETE 三种写语句使你在同一批次中可以先定义一个聚合结果再基于该结果执行删除、更新或插入从而减少往返、提升事务内一致性。1.1 最小可用示例WITH DELETE RETURNINGchangelog 中给出的典型场景是删除金额高于平均值的订单其中平均值通过 CTE 预先计算const averageAmount db.$with(average_amount).as( db.select({ value: sqlavg(${orders.amount}).as(value) }).from(orders), ); const result await db .with(averageAmount) .delete(orders) .where(gt(orders.amount, sql(select * from ${averageAmount}))) .returning({ id: orders.id, });生成的 SQL 为with average_amount as (select avg(amount) as value from orders) delete from orders where orders.amount (select * from average_amount) returning id写法上完全复用了 SELECT 场景的既有 API 习惯先用db.$with(alias).as(queryBuilder)定义一个带别名的 CTE再在.with(cte)之后链式调用.insert() / .update() / .delete()。这意味着只要你的方言PostgreSQL / MySQL / SQLite 等支持 CTE 写操作同一套 TypeScript 代码即可跨数据库复用。1.2 底层实现WithSubquery与$with的构建链路从源码看CTE 的运行时载体是 drizzle-orm/src/subquery.ts 中的两个类Subquery普通子查询的基类构造时接收 SQL、选中字段、别名并带有isWith与usedTables标记WithSubquery继承自Subquery专门标识通过$with创建的 CTE 对象。每个方言的数据库实例都暴露了$with与with两个方法。以 PostgreSQL 为例pg-core/db.ts 中$with(alias, selection?)返回{ as }对象as接收一个查询构建器也支持传入普通SQL或接收QueryBuilder的回调函数内部通过new Proxy(new WithSubquery(...), new SelectionProxyHandler(...))创建带别名代理的 CTE 对象而with(...queries)则负责把这些 CTE 注入主查询的 SQL 前缀见 pg-core/db.ts。同理db.with(sq).select().from(sq)这一既有用法在 pg-core/db.ts 的 JSDoc 中有完整示例。需要特别留意的是 CTE 内任意 SQL 值的别名要求$with的 JSDoc 明确指出若要在 CTE 中选出sql原始表达式并供外层查询引用必须给该表达式追加.as(name)别名例如sqlstringupper(${users.name}).as(name)。changelog 示例中的sqlavg(${orders.amount}).as(value)正是这一约束的直接体现——聚合值不取别名时外层select * from ${averageAmount}将无法通过类型检查。1.3 实战扩展同样的模式可以推广到 INSERT 与 UPDATEWITH INSERT可先在 CTE 中计算或过滤出候选行集再通过insert ... select批量写入目标表WITH UPDATE先聚合每个分组的统计值再回写主表例如把每类商品的平均售价写回分类表多 CTE 串联db.with(cte1, cte2, ...)支持一次注入多个 CTE后续 CTE 可引用先前 CTE 的结果用于构造多阶段流水线式写操作。关于各语句的更多官方示例可查阅仓库 changelog 原文 changelogs/drizzle-orm/0.29.5.md 中列出的 INSERT / UPDATE / DELETE 分节说明。二、自定义迁移记录表migrationsTable与migrationsSchemaDrizzle ORM 默认会把已执行迁移的元数据记录在__drizzle_migrations表中对 PostgreSQL 而言该表默认位于drizzleschema 内。0.29.5 由 g3r4n 贡献允许开发者通过两个新配置项完全自定义迁移记录的存储位置从而适配既有的数据库命名规范、多租户隔离或权限约束。2.1 配置项定义统一配置接口定义在 drizzle-orm/src/migrator.tsexport interface MigrationConfig { migrationsFolder: string; migrationsTable?: string; migrationsSchema?: string; }migrationsFolder必填存放meta/_journal.json与各迁移 SQL 文件的目录readMigrationFiles()会读取该目录下的_journal.json并按条目依次加载对应.sql文件见 migrator.tsmigrationsTable可选自定义迁移记录表的表名默认__drizzle_migrationsmigrationsSchema可选仅对 PostgreSQL以及基于其协议的数据库生效自定义迁移记录所在 schema默认drizzle。2.2 自定义表名migrationsTable所有驱动PostgreSQL、MySQL、SQLite、LibSQL、Neon、Xata、D1 等的 migrator 都会读取该配置。以 SQLite Proxy 的 migrator 为例sqlite-proxy/migrator.ts表名解析逻辑为const migrationsTable typeof config string ? __drizzle_migrations : config.migrationsTable ?? __drizzle_migrations;即当config直接以字符串传入旧式用法时使用默认表名传入对象时优先取migrationsTable。随后建表语句为CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsTable)} (...)记录查询与写入也都会使用该表名。用法示例await migrate(db, { migrationsFolder: ./drizzle, migrationsTable: my_migrations, });2.3 自定义 schemamigrationsSchema仅 PostgreSQL兼容性前提migrationsSchema仅对 PostgreSQL 数据库生效MySQL / SQLite / SingleStore 的配置类型中明确排除了该字段见 mysql-core/dialect.ts 与 singlestore-core/dialect.ts 中的OmitMigrationConfig, migrationsSchema。PostgreSQL 侧的实现位于 pg-core/dialect.ts默认值为drizzle建表时使用${sql.identifier(migrationsSchema)}.${sql.identifier(migrationsTable)}双标识符限定并且会先执行CREATE SCHEMA IF NOT EXISTS确保 schema 存在查询与写入迁移记录时同样使用 schema 限定名。Neon HTTP 驱动的 migrator 也有完全一致的逻辑见 neon-http/migrator.ts。用法示例await migrate(db, { migrationsFolder: ./drizzle, migrationsSchema: custom, });此时迁移记录将写入custom.__drizzle_migrations表若同时指定migrationsTable: my_migrations则为custom.my_migrations。2.4 迁移执行流程回顾无论迁移记录存在哪里执行逻辑都遵循同一套流程见 migrator.ts读取meta/_journal.json→ 按journal.entries逐个加载对应 tag 的 SQL 文件 → 以-- statement-breakpoint分割语句 → 计算每个文件的 SHA-256 哈希。随后 migrator 查询迁移表中created_at最新的记录仅对时间戳更新的迁移文件执行 SQL并在执行后插入(hash, created_at)记录实现增量迁移与幂等保障。三、SQLite Proxy批量查询与关系查询支持SQLite Proxy 驱动让 Drizzle ORM 不必直接连接 SQLite 文件或原生绑定而是通过你自定义的 HTTP / RPC 回调与远程代理服务通信。0.29.5 为该驱动补齐了两项与其他驱动看齐的能力.query.findFirst / .query.findMany关系查询语法以及db.batch([])批量请求。3.1 驱动类型定义在 sqlite-proxy/driver.ts 中两类回调的类型签名如下export type AsyncRemoteCallback ( sql: string, params: any[], method: run | all | values | get, ) Promise{ rows: any[] }; export type AsyncBatchRemoteCallback (batch: { sql: string; params: any[]; method: run | all | values | get; }[]) Promise{ rows: any[] }[];drizzle()工厂函数对这两个参数做了重载兼容既可以只传单个回调也可以传单查询回调 批量回调两个参数见 sqlite-proxy/driver.ts批量回调在第二个参数位置传入。3.2 初始化带批量回调的数据库实例changelog 给出的完整示例已在原示例基础上补充 axios 导入等运行前提import { drizzle } from drizzle-orm/sqlite-proxy; type ResponseType { rows: any[][] | any[] }[]; const db drizzle( async (sql, params, method) { // 单条查询逻辑发送到代理服务器 // 例如 axios.post(http://localhost:3000/query, { sql, params, method }) }, // 新增的批量回调 async ( queries: { sql: string; params: any[]; method: all | run | get | values; }[], ) { try { const result: ResponseType await axios.post( http://localhost:3000/batch, { queries }, ); return result; } catch (e: any) { console.error(Error from sqlite proxy server:, e); throw e; } }, );配置完成后即可调用db.batch([])框架会把数组内的多条查询统一转发给批量回调const [users, orders] await db.batch([ db.select().from(users), db.select().from(orders), ]);3.3 批量响应的格式约定响应必须是与发送顺序一致的原始值数组组成的数组array of arrays即ResponseType { rows: any[][] | any[] }[]每个元素对应一条查询的rows结果。顺序错乱或结构不符都会导致结果映射错误。这条约定源于AsyncBatchRemoteCallback的类型定义sqlite-proxy/driver.ts回调接收{ sql, params, method }[]返回{ rows }[]实现时务必按queries的索引逐一返回结果。3.4 关系查询与批量能力的落地.query.findFirst()/.query.findMany()这是 Drizzle 的关系查询relational queries入口需要配合relations定义与 schema 配置使用。SQLite Proxy 的数据库类继承自BaseSQLiteDatabasesqlite-proxy/driver.ts其会话层支持关系查询所需的查询构建与结果解析因此传入包含schema: { ...tables, ...relations }的配置后即可使用db.query.users.findMany({ with: { posts: true } })语法db.batch([])SQLite Proxy 的SqliteRemoteDatabase显式实现了batch()方法委托给session.batch()sqlite-proxy/driver.ts批量行为与 libsql、better-sqlite3 等其他 SQLite 驱动保持一致。四、适用范围与升级建议特性适用数据库关键配置/API源码位置WITH INSERT / UPDATE / DELETEPostgreSQL / MySQL / SQLite 等支持 CTE 的方言db.$with(alias).as(...)db.with(cte).insert/update/deletedrizzle-orm/src/subquery.ts、pg-core/db.tsmigrationsTable全部支持 migrate 的驱动migrate(db, { migrationsTable: xxx })drizzle-orm/src/migrator.tsmigrationsSchema仅 PostgreSQL / Neon 等 PG 系migrate(db, { migrationsSchema: xxx })pg-core/dialect.ts、neon-http/migrator.tsSQLite Proxy 批量查询sqlite-proxy第二个回调参数 db.batch([])sqlite-proxy/driver.ts、sqlite-proxy/migrator.tsSQLite Proxy 关系查询sqlite-proxydb.query.findFirst / findMany relations 配置sqlite-proxy/driver.ts升级建议若你正在使用自建 SQLite 代理服务或需要把迁移记录纳入企业级 schema 治理0.29.5 的这三项能力均可在不破坏既有 API 的前提下平滑启用所有新配置项均为可选默认行为与旧版本完全一致。升级后建议优先用WITH DELETE ... RETURNING重构多步写流程并用migrationsSchema将迁移元数据与业务数据隔离到独立 schema。完整的版本说明原文见 changelogs/drizzle-orm/0.29.5.md仓库中还包含各方言的会话层与测试代码如 drizzle-orm/tests、integration-tests/tests可供进一步验证上述行为。【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Matter Darwin Framework 实战指南:connectedhomeip 中 Matter.framework 的构建与 Zap 代码再生

Matter Darwin Framework 实战指南:connectedhomeip 中 Matter.framework 的构建与 Zap 代码再生

Matter Darwin Framework 实战指南:connectedhomeip 中 Matter.framework 的构建与 Zap 代码再生 【免费下载链接】connectedhomeip Matter (formerly Project CHIP) creates more connections between more objects, simplifying development for manufacturers an…

2026/9/19 12:22:33 阅读更多 →
OfficeCLI 内容控件(Content Controls)完全指南:用 CLI 与 Python SDK 构建 Word 可填写表单

OfficeCLI 内容控件(Content Controls)完全指南:用 CLI 与 Python SDK 构建 Word 可填写表单

OfficeCLI 内容控件(Content Controls)完全指南:用 CLI 与 Python SDK 构建 Word 可填写表单 【免费下载链接】OfficeCLI OfficeCLI 是首款也是最佳的专为 AI 代理设计的命令行工具,可用于读取、编辑和自动化处理 Word、Excel 和 …

2026/9/19 12:22:33 阅读更多 →
常州网站建设套餐怎么选:3个实战案例教你避坑

常州网站建设套餐怎么选:3个实战案例教你避坑

常州网站建设套餐怎么选:3个实战案例教你避坑 别再被那些花里胡哨的模板网站忽悠了。上周刚帮一个做五金机械的客户,把用了两年的模板站给换掉,客户看着后台那堆乱七八糟的代码和根本搜不到关键词的页面,脸都绿了。这就是典型的“模板网站太丑不够用”,不仅形象拉胯,还严重拖累了生意转化。…

2026/9/19 12:22:05 阅读更多 →

最新新闻

汽车行业APQP全流程解析:从DFMEA到控制计划的落地指南

汽车行业APQP全流程解析:从DFMEA到控制计划的落地指南

简介:这份APQP 2008第二版中文版PDF资料,面向汽车及制造业质量管理人员、体系工程师及项目策划人员,系统讲解了产品质量先期策划与控制计划的核心方法论。内容涵盖APQP定义与五大阶段流程、质量管理基本原则、组织架构搭建、人员培训要求&…

2026/9/20 15:02:24 阅读更多 →
Evidently:用一套 Python 库跑通 ML/LLM 的评估、测试与监控

Evidently:用一套 Python 库跑通 ML/LLM 的评估、测试与监控

Evidently:用一套 Python 库跑通 ML/LLM 的评估、测试与监控 【免费下载链接】evidently Evidently is ​​an open-source ML and LLM observability framework. Evaluate, test, and monitor any AI-powered system or data pipeline. From tabular data to Gen A…

2026/9/20 15:02:24 阅读更多 →
BoxMOT 多目标跟踪实践指南:从算法选型到可复现评测

BoxMOT 多目标跟踪实践指南:从算法选型到可复现评测

BoxMOT 多目标跟踪实践指南:从算法选型到可复现评测 【免费下载链接】boxmot BoxMOT: Pluggable Python and C SOTA multi-object tracking modules with support for axis-aligned and oriented bounding boxes 项目地址: https://gitcode.com/GitHub_Trending/b…

2026/9/20 15:02:24 阅读更多 →
CC Switch 指向 TaoToken:Qwen3.7 Flash 设为默认供应商

CC Switch 指向 TaoToken:Qwen3.7 Flash 设为默认供应商

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 15:02:24 阅读更多 →
OpenClaw 加载供应商技能报 401?TaoToken 这样改模型通道

OpenClaw 加载供应商技能报 401?TaoToken 这样改模型通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 15:02:24 阅读更多 →
VMware Workstation Pro 25H2下载安装与汉化完整指南

VMware Workstation Pro 25H2下载安装与汉化完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 15:01:24 阅读更多 →

日新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →