You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用$queryRaw在Prisma中执行PostgreSQL的to_char函数

可行方案说明

截至Prisma当前正式稳定版本,不存在完全不使用原生查询、仅靠内置链式语法直接调用to_char等PostgreSQL原生函数的实现方式。你预期的在findMany参数内直接传入数据库函数的写法,目前官方没有支持计划——这类和特定数据库绑定的函数语法差异极大,作为跨数据库ORM,Prisma不会内置覆盖所有数据库方言的私有函数。

如果不想写整段原生SQL,可以用以下两种可落地的方案实现需求:

方案1:新增数据库存储生成列(推荐,完全符合无原生查询要求)

通过Prisma支持的dbgenerated属性,在表中新增一个由数据库自动维护的冗余字段,预存日期对应的月日数值,后续所有筛选排序直接针对该字段操作,全程使用Prisma普通查询语法。

  1. 首先修改Prisma Schema,新增生成列:
model User {
  id            Int       @id @default(autoincrement())
  birthdate     DateTime
  // 数据库自动计算存储MMDD格式数值,例:10月5日存储为1005,无需业务代码手动传值
  birthdateMmdd Int       @default(
    dbgenerated("EXTRACT(MONTH FROM birthdate)::int * 100 + EXTRACT(DAY FROM birthdate)::int")
  )
  // 其余业务字段...
}

修改后执行prisma migrate dev生成并执行数据库迁移即可,历史数据的birthdateMmdd字段会由数据库自动补全。

  1. 业务代码中直接使用普通查询实现需求:
// 计算当前日期对应的MMDD数值
const now = new Date()
const currentMmdd = (now.getMonth() + 1) * 100 + now.getDate()

// 完全走Prisma标准链式调用,无任何原生SQL
const userList = await this.prismaService.user.findMany({
  where: {
    birthdateMmdd: {
      gte: currentMmdd
    }
  },
  orderBy: {
    birthdateMmdd: 'asc'
  }
})

该方案优缺点:

  • 优势:完全满足无原生查询的要求,查询性能远高于运行时逐行调用to_char,可以给birthdateMmdd加索引进一步提升大表查询速度
  • 劣势:需要修改表结构,已上线的大表需要执行迁移操作

方案2:保留现有原生查询写法(无需改表)

如果你完全不能接受修改表结构,你目前使用的$queryRaw参数化查询写法已经是不改表前提下的最优实现,不存在其他绕开原生查询的取巧方式。注意写原生查询时始终使用Prisma.sql标签做参数转义,避免SQL注入风险即可。

注:不要尝试通过Prisma中间件、客户端扩展等能力hack查询语法实现类似效果,这类实现本质还是在底层拼接原生SQL,维护成本和稳定性远不如上面两种方案。


内容的提问来源于stack exchange,提问作者Birtalan Robert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:24:20