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

PostgreSQL查询在pgAdmin正常运行,Prisma ORM执行失败求助

Prisma $queryRawUnsafe 参数化查询失败的解决方法

问题根源

你的代码存在两个核心问题:

  • 列名不能用参数化占位符:$1和$2被PostgreSQL解析为字符串值(比如"shift_end"),而非实际列名,导致执行text - text时无对应运算符,触发42883错误。
  • 日期参数错误添加单引号:'$3'会让PostgreSQL把$3当成字符串字面量,而非参数占位符,解析日期时触发22007错误。

修正后的代码

// 先验证列名合法性,防止SQL注入
const allowedColumns = ['shift_start', 'shift_end', 'break_start', 'break_end'];
if (!allowedColumns.includes(end) || !allowedColumns.includes(start)) {
  throw new Error('Invalid column name');
}

const decimalDuration: { totalDuration: number }[] = await this.client.$queryRawUnsafe(`
  SELECT SUM(EXTRACT(EPOCH FROM (${end} - ${start}))) / 3600 AS "totalDuration"
  FROM shift
  WHERE ${start} > $1
  AND work_place_id = $2
`,
earliest,
workPlaceId
);

关键说明

  1. 列名处理:直接用字符串拼接列名,但必须先验证列名在允许列表中,避免SQL注入风险。参数化查询的占位符仅适用于值,不能用于列名、表名这类标识符。
  2. 日期参数:直接传入Date类型的earliest,Prisma会自动转换为PostgreSQL的timestamp类型,无需手动加单引号或类型转换。
  3. UUID参数:workPlaceId作为UUID字符串传入即可,Prisma会自动处理类型匹配,无需额外加::uuid。

逻辑验证

修正后的查询和你在pgAdmin中运行的语句逻辑完全一致:

  • 列名直接使用变量对应的实际列(如shift_end和shift_start)
  • 日期条件正确对比timestamp类型
  • UUID匹配逻辑保持不变

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:13:06