文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载导读本文以 TIL 仓库中的 execute-a-raw-sql-query.md 为主体讲解 PrismaTypeScript在常规生成式 API 无法满足查询需求时如何通过$queryRaw标签模板函数执行原生 SQL。你将掌握$queryRaw的完整用法、结果结构、参数注入方式以及一个真实场景——在 PostgreSQL 中利用date_trunc与 interval 运算计算门票剩余有效期并了解原生查询时的安全边界与调试手段。为什么 ORM 需要逃生舱Prisma 作为一款强大的 ORM 与 batch-insert-records-with-create-many.md。但并非所有查询都能被生成式 API覆盖某些表并未被纳入schema.prisma比如旁路表、历史归档表、外部数据源它们没有对应的 Model自然无法通过客户端方法访问需要手写查询以追求性能或表达力一条复杂的 JOIN、窗口函数或数据库专有函数用 ORM 方法链拼出来既晦涩又低效。面对这类情况Prisma 提供了一个逃生舱escape hatch$queryRaw标签函数。所谓标签模板字符串tagged template literal就是把模板字符串交给一个函数处理函数可以同时拿到静态 SQL 片段和插值变量从而安全地构造参数化查询。$queryRaw 基本用法与结果形态下面是从原文档继承的完整示例——查询某邮箱用户的购票记录并实时计算每张票的剩余有效期function getExpiresIn({ email }) { const prisma new PrismaClient() const result: Arrayobject await prisma.$queryRaw select id, code, date_trunc(days, expires_at - now())::varchar as expires_in from tickets where email ${email} // result // [{ id: 123, code: abc123, expires_in: 3 days }] return result }这段代码的要点模板字符串即 SQL 本体$queryRaw会把模板字面量中的内容原样发送给数据库执行${email}不是字符串拼接插值部分会被作为参数占位符传入Prisma 负责参数绑定parameterized query避免手写 SQL 时常见的注入风险返回结构执行结果是一个对象数组每个对象以列名 → 值的键值对呈现。示例中每条记录得到id、code、expires_in三个键类型注解示例将结果声明为Arrayobject。如果希望获得更精确的字段提示可以给$queryRaw传入泛型类型例如prisma.$queryRawArray{ id: number; code: string; expires_in: string }\...。利用数据库特性PostgreSQL 的 date_trunc 与 interval 运算手写 SQL 的最大收益在于可以直接使用数据库专有能力。示例查询针对的是 PostgreSQL其中两处特性是 Prisma 生成式 API 难以优雅表达的date_trunc(days, ...)把时间戳截断到指定精度。这里将expires_at - now()的差值截断到天再通过::varchar转成字符串输出。interval 运算expires_at - now()在 PostgreSQL 中天然产生interval类型可以直接参与日期数学。仓库 postgres/different-ways-to-define-an-interval.md 展示了 interval 的多种定义方式包括interval 3 days字面量、3 days::interval类型转换以及make_interval(days 3)函数——这说明 interval 是 PostgreSQL 一等公民类型原生 SQL 中可自由组合这些写法。值得注意date_trunc(days, ...)::varchar会产生类似3 days或0 days的字符串。若需在 JavaScript 侧做进一步日期运算更稳妥的做法是直接返回interval类型或时间戳差值由应用层格式化。正确选择$queryRaw 与 $executeRaw 的边界Prisma 的原生访问不止$queryRaw一个入口按用途可区分方法适用场景返回$queryRaw返回数据的SELECT类查询对象数组$queryRawUnsafe无法使用标签模板如 SQL 以字符串变量动态拼接时对象数组需自行保证安全$executeRaw不返回数据行的写入类操作INSERT/UPDATE/DELETE受影响行数$executeRawUnsafe同$executeRaw但接受普通字符串 SQL受影响行数从源码文档定位看Prisma 官方 raw database access 是这些 API 的依据来源。优先使用带标签模板的$queryRaw它能利用模板字符串的插值机制把变量安全地传给驱动层做参数绑定Unsafe变体则要求调用方对 SQL 内容与转义完全负责属于知道自己在做什么时的选项。安全要点为什么不要用字符串拼接写原生 SQL 最大的风险是 SQL 注入。对比两种写法// 安全变量交给模板标签处理作为参数绑定不参与 SQL 文本解析 await prisma.$queryRawselect * from tickets where email ${email} // 危险把用户输入直接拼进 SQL 文本 await prisma.$executeRawUnsafe(select * from tickets where email ${email})$queryRaw的模板插值在 Prisma 内部被转换为驱动层的参数占位符数据库看到的是结构固定的 SQL 参数值用户输入永远不可能改变查询结构而字符串拼接会把输入当作 SQL 文本的一部分一旦输入包含、--等字符即可改写语句语义。凡是变量来自请求参数、表单或其他不可信来源务必走模板标签语法。调试辅助开启 SQL 日志手写 SQL 出错时最直接的手段是确认实际发往数据库的语句。仓库 configure-client-to-log-sql-queries.md 提供了一种简单方案在初始化PrismaClient时开启日志export const prisma new PrismaClient({ log: [error, query] })若只想在开发环境打印 SQL可结合环境变量export const prisma new PrismaClient({ log: process.env.NODE_ENV development ? [query, error] : [error], })这样当包含原生查询的代码路径执行时应用服务器日志中就会出现对应的 SQL 语句行便于核对参数绑定后的真实语句。小结$queryRaw是 Prisma 生态中连接类型安全 ORM与数据库原生能力的桥梁当生成式 API 覆盖不到的查询未建模的表、复杂窗口函数、date_trunc与 interval 运算这类数据库专有特性出现时它可以保持参数化查询的安全性同时把 SQL 的表达力完整交还给开发者。实践要点可归纳为能用模板标签语法就用$queryRaw让 Prisma 负责参数绑定结果总是对象数组必要时用泛型收紧返回类型写操作用$executeRawUnsafe 变体留给完全可控的动态 SQL 场景开发期配合log: [query, error]观察真实执行语句降低调试成本。对 PostgreSQL 日期能力感兴趣可继续阅读仓库 postgres/different-ways-to-define-an-interval.md 与 postgres/constructing-a-range-of-dates.md它们与本文的expires_in计算逻辑直接呼应。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐用autocannon进行数据库查询性能测试ORM与原生SQL对比用autocannon进行数据库查询性能测试ORM与原生SQL对比 数据库查询性能直接影响应用响应速度而选择ORM对象关系映射还是原生SQL一直是开发者性能测试测试开发工具Rust数据库操作ORM与原生SQL查询的最佳实践Rust数据库操作ORM与原生SQL查询的最佳实践 在现代软件开发中数据库操作是核心功能之一。Rust作为一门注重安全和性能的系统级编程语言提供了多种数据编程语言编译器语言运行时标准库Prisma项目中关于queryRaw方法默认使用主库的技术解析Prisma项目中关于queryRaw方法默认使用主库的技术解析 在数据库应用开发中读写分离是一种常见的架构设计模式通过将读操作分发到从库 replica数据库ORM后端数据建模上一篇碧蓝航线Alas自动化脚本告别重复劳动享受智能游戏体验下一篇DLSS Swapper终极指南如何轻松管理游戏DLSS/FSR/XeSS文件提升性能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考