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 );
关键说明
- 列名处理:直接用字符串拼接列名,但必须先验证列名在允许列表中,避免SQL注入风险。参数化查询的占位符仅适用于值,不能用于列名、表名这类标识符。
- 日期参数:直接传入
Date类型的earliest,Prisma会自动转换为PostgreSQL的timestamp类型,无需手动加单引号或类型转换。 - UUID参数:
workPlaceId作为UUID字符串传入即可,Prisma会自动处理类型匹配,无需额外加::uuid。
逻辑验证
修正后的查询和你在pgAdmin中运行的语句逻辑完全一致:
- 列名直接使用变量对应的实际列(如
shift_end和shift_start) - 日期条件正确对比timestamp类型
- UUID匹配逻辑保持不变
内容的提问来源于stack exchange,提问作者IdoBa
相关产品推荐
相关产品推荐

