如何修复Postgres错误:绑定消息提供8个参数,但预准备语句仅需要6个
问题根因
你的报错是SQL占位符数量和传入的参数数组长度不匹配导致的:
- 你写的SQL里占位符最大编号为6,意味着只需要传入6个参数
- 你实际传入的参数数组有8个值,多了2个无效参数,同时还存在占位符编号错误、参数遗漏的问题
具体问题点
- PostgreSQL的查询占位符是全局按顺序计数的,你把
t1占了$1的位置后,tab2对应的字段参数应该从$2开始计数,你之前写的SELECT $1,$2...重复用了$1,取值逻辑完全错误 id_tab2是从tab1插入后返回的自增ID,不需要你从前端传也不需要放入参数数组- 参数数组里多了明文的
x4(你已经把x4加密成hashedPassword,不需要再传明文),还漏了x5字段 - 你在返回用户已存在的响应后没有加
return,会导致后续代码继续执行,抛出响应头重复发送的错误 - 错误状态码使用不规范,用户已存在应该返回409冲突,服务端报错应该返回500,不要全部用404
修复后的后端代码
const createUser = (req, res, next) => { const con = req.con // 删掉不需要接收的id_tab2 const { t1, x1, x2, x3, x4, x5, x6 } = req.body con.query( `SELECT * FROM users WHERE x3 = $1`, [x3], (err, results) => { if (err) { console.log(err) // 加return避免后续代码执行,修改为合理的服务端错误状态码 return res.status(500).json({ message: err }) } if (results.rows.length > 0) { // 加return,修改为资源冲突状态码 return res.status(409).json({ message: "user exists" }) } const hashedPassword = bcrypt.hashSync(x4, parseInt(process.env.BCRYPT_ROUNDS)) // 修正SQL占位符编号,$1对应tab1的t1,$2~$7对应tab2的6个业务字段 const insertSql = ` WITH ins1 AS ( INSERT INTO tab1(t1) VALUES ($1) RETURNING id AS id_tab2 ), ins2 AS ( INSERT INTO tab2 (x1,x2,x3,x4,x5,x6,id_tab2) SELECT $2,$3,$4,$5,$6,$7,id_tab2 FROM ins1 RETURNING x1, x2, x3, x4, x5, x6, id_tab2 ) SELECT * FROM ins2 ` // 修正参数数组,共7个参数和SQL占位符一一对应,删掉无效参数、补上x5 con.query( insertSql, [t1, x1, x2, x3, hashedPassword, x5, x6], (err, results) => { if (err) { console.log(err) return res.status(500).json({ message: err }) } res.status(200).send(results.rows[0]) } ) } ) }
前端代码可选修复
你前端的axios调用多了一个多余的闭合括号,也可以一并修正,避免语法问题:
axios.post("/accnt/register", data) .then((res) => { this.$emit("addedUser", res.data) message.success(`user added`) }) .catch((e) => { message.warning(e.response?.data?.message || '请求失败') console.log('error', e) })
内容的提问来源于stack exchange,提问作者Cyrine
相关产品推荐
相关产品推荐

