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

导入数据库后注册用户遇ER_DUP_ENTRY主键重复错误及密码哈希问题

问题解决:主键重复错误与管理员密码哈希处理

一、主键重复错误解决

问题描述

迁移数据库后注册新用户报错:

Error: ER_DUP_ENTRY: Duplicate entry '0' for key 'PRIMARY'

确认原因:users表的id主键未设置自增,新环境插入数据时默认从0开始计数,与已有数据冲突。

最优解决方案:修改表结构开启自增

直接执行SQL修改表结构,让id字段自动递增,这是彻底解决主键冲突的方法,无需修改业务代码:

ALTER TABLE users MODIFY COLUMN id INT AUTO_INCREMENT PRIMARY KEY;

执行后MySQL会自动识别当前表中最大的id值,后续插入数据时自动从最大值+1生成新主键,完全避免重复问题。

临时方案(不推荐,存在并发风险)

如果暂时无法修改表结构,需手动计算新主键,但要修复你写的异步函数问题:
原findId函数因db.query是异步操作,无法正确返回值,需改为Promise形式:

async function getMaxId() {
  return new Promise((resolve, reject) => {
    db.query("SELECT MAX(id) as maxId FROM users", (error, results) => {
      if (error) reject(error);
      // 若表为空则默认从1开始
      const maxId = results[0].maxId || 0;
      resolve(maxId + 1);
    });
  });
}

然后修改注册控制器逻辑,调用该函数获取新主键后插入:

exports.register = async (req, res) => {
    console.log(req.body);
    const { username, email, password, passwordConfirm } = req.body;

    try {
        // 查询用户名/邮箱是否存在
        const existingUsers = await new Promise((resolve, reject) => {
            db.query(
                'SELECT username,email FROM users WHERE username = ? OR email = ?',
                [username, email],
                (err, results) => err ? reject(err) : resolve(results)
            );
        });

        if (existingUsers.length > 0) {
            return res.render('register', { message: '用户名或邮箱已存在' });
        }
        if (password !== passwordConfirm) {
            return res.render('register', { message: '两次密码不一致' });
        }

        // 哈希密码
        const hashPassword = await bcrypt.hash(password, 8);
        // 获取新主键id
        const newUserId = await getMaxId();

        // 插入新用户
        await new Promise((resolve, reject) => {
            db.query(
                'INSERT INTO users SET ?',
                { id: newUserId, username, email, password: hashPassword, admin: 0 },
                (err) => err ? reject(err) : resolve()
            );
        });

        return res.render('register', { message: '用户注册成功' });
    } catch (error) {
        console.error(error);
        return res.render('register', { message: '注册失败,请重试' });
    }
};

⚠️ 注意:该方案在多用户同时注册时可能出现主键冲突,仅作为临时过渡方案使用。

二、已存在管理员账户密码哈希处理

方法1:手动生成哈希并更新

  1. 运行以下代码生成密码哈希值(替换为管理员的真实密码):
const bcrypt = require('bcrypt');
(async () => {
  const hash = await bcrypt.hash('管理员密码', 8);
  console.log(hash); // 复制输出的哈希字符串
})();
  1. 执行SQL更新管理员用户的密码(替换id和哈希值):
UPDATE users SET password = '生成的哈希字符串' WHERE id = 1;

方法2:批量更新脚本

如果有多个管理员用户,可编写脚本批量处理:

const bcrypt = require('bcrypt');
const db = require('./你的数据库连接文件'); // 替换为实际的数据库连接路径

async function updateAdminPasswords() {
  try {
    // 查询所有管理员(假设admin字段为1代表管理员)
    const admins = await new Promise((resolve, reject) => {
      db.query('SELECT id FROM users WHERE admin = 1', (err, results) => err ? reject(err) : resolve(results));
    });

    for (const admin of admins) {
      const hashPassword = await bcrypt.hash('管理员统一密码', 8);
      await new Promise((resolve, reject) => {
        db.query(
          'UPDATE users SET password = ? WHERE id = ?',
          [hashPassword, admin.id],
          (err) => err ? reject(err) : resolve()
        );
      });
      console.log(`已更新ID为${admin.id}的管理员密码`);
    }

    console.log('所有管理员密码更新完成');
    db.end(); // 关闭数据库连接
  } catch (error) {
    console.error(error);
    db.end();
  }
}

updateAdminPasswords();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:37:33