导入数据库后注册用户遇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:手动生成哈希并更新
- 运行以下代码生成密码哈希值(替换为管理员的真实密码):
const bcrypt = require('bcrypt'); (async () => { const hash = await bcrypt.hash('管理员密码', 8); console.log(hash); // 复制输出的哈希字符串 })();
- 执行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
相关产品推荐
相关产品推荐

