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

NodeJS用Prepared Statements插入PostgreSQL报错:syntax error at or near "$"求助

解决PostgreSQL Prepared Statements中"syntax error at or near "$""的问题

我帮你定位到了几个导致错误的核心问题,咱们一步步来修复:

1. PostgreSQL占位符格式错误

PostgreSQL的Prepared Statements不支持$id这种命名式占位符,只能使用$1、$2这种按参数顺序排列的数字占位符。你在INSERT语句里写的$id直接触发了语法错误,这是最关键的问题。

2. SERIAL主键不需要手动插入值

你的userId是SERIAL类型,这是PostgreSQL的自增主键,数据库会自动为它生成递增的数值,所以INSERT操作时根本不需要把它包含在列列表里,也不用传对应的空参数。

3. 密码没有使用哈希后的值

你调用bcrypt.hash生成了密码哈希,但最后插入数据库的还是原密码this.user.password,既不符合你的代码逻辑,也存在安全隐患。

4. async函数混用回调的问题

save方法标记了async,但内部却用了.then()回调,建议统一用await让异步逻辑更清晰,也避免回调嵌套带来的维护问题。


修复后的完整代码

class Employees {
  constructor(user) {
    this.client = require("../database");
    this.createTable();
    this.bcrypt = require("bcrypt");
    this.user = user;
  }

  createTable() {
    this.client.query(
      "CREATE TABLE IF NOT EXISTS employees(userId SERIAL, firstName varchar(255) NOT NULL, lastName varchar(255) NOT NULL, email varchar(255) NOT NULL, password varchar(255) NOT NULL, gender varchar(255) NOT NULL, jobRole varchar(255) NOT NULL, department varchar(255) NOT NULL, address varchar(255) NOT NULL, PRIMARY KEY (userId))",
      (err, res) => {
        console.log("ERROR ==> " + err);
        console.log("RESPONSE ==> " + res);
      }
    );
  }

  // 修复后的save方法
  async save() {
    try {
      // 用await替代then,简化异步逻辑
      const hash = await this.bcrypt.hash(this.user.password, 10);
      // 移除userId列,让数据库自动处理自增
      const sql = `INSERT into employees (firstName, lastName, email, password, gender, jobRole, department, address) 
                   VALUES($1, $2, $3, $4, $5, $6, $7, $8) 
                   RETURNING userId`;
      // 参数顺序与占位符一一对应,使用哈希后的密码
      const params = [
        this.user.firstName,
        this.user.lastName,
        this.user.email,
        hash,
        this.user.gender,
        this.user.jobRole,
        this.user.department,
        this.user.address
      ];
      const res = await this.client.query(sql, params);
      console.log("RESPONSE ==> ", res.rows[0]); // 打印返回的自增userId
    } catch (error) {
      console.log("ERROR ==> ", error);
    }
    // 注意:如果client是全局复用的连接,不要在这里调用end(),否则后续请求会失败
    // await this.client.end();
  }
}

module.exports = Employees;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:36:07