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

NodeJS+MySQL注册功能误判邮箱/用户名已存在问题排查

NodeJS + MySQL 用户注册校验异常问题

我正在开发基于NodeJS和MySQL的用户注册功能,需求是校验邮箱和用户名是否已存在于系统中,若存在则提示对应信息,不存在则允许注册。但实际测试时,即便数据库中无对应邮箱或用户名,系统仍提示“Email already exists”或“Username already exists”。

注册功能代码

const bcrypt = require("bcryptjs");
const avatars = require("../databases/avatar.js");
const mysqlConnection = require("../databases/connect-mysql.js");
const jwt = require("jsonwebtoken");
const otpGenerator = require("otp-generator");

function getRandomAvatar() {
  const randomIndex = Math.floor(Math.random() * avatars.length);
  return avatars[randomIndex].avatar;
}

async function register(req, res) {
  try {
    const { USERNAME, EMAIL, PASSWORD, FIRST_NAME, LAST_NAME } = req.body;

    if (!EMAIL) {
      return res.status(400).send("Email cannot be empty");
    }
    // 校验邮箱是否已存在
    const emailExistQuery = `SELECT * FROM USERS WHERE EMAIL = ?`;
    const emailAlreadyExists = await mysqlConnection.query(emailExistQuery, [
      EMAIL,
    ]);
    if (emailAlreadyExists.length > 0) {
      return res.status(400).send("Email already exists");
    }

    // 校验用户名是否已存在
    const usernameExistQuery = `SELECT * FROM USERS WHERE USERNAME = ?`;
    const usernameAlreadyExists = await mysqlConnection.query(
      usernameExistQuery,
      [USERNAME]
    );

    if (usernameAlreadyExists.length > 0) {
      return res.status(400).send("Username already exists");
    }

    const salt = bcrypt.genSaltSync(10);
    const hashedPassword = await bcrypt.hash(PASSWORD, salt);

    const insertUserQuery = `
      INSERT INTO users (USERNAME, EMAIL, PASSWORD, AVATAR, FIRST_NAME, LAST_NAME)
      VALUES (?, ?, ?, ?, ?, ?)`;

    const newUserValues = [
      USERNAME,
      EMAIL,
      hashedPassword,
      getRandomAvatar(),
      FIRST_NAME,
      LAST_NAME,
    ];

    await mysqlConnection.query(insertUserQuery, newUserValues);

    return res.status(200).send("User has been created");
  } catch (error) {
    return res.status(500).send({ error: error.message });
  }
}

MySQL表结构

CREATE TABLE USERS (
    ID CHAR(36) DEFAULT (UUID()) PRIMARY KEY,
    USERNAME VARCHAR(255) UNIQUE NOT NULL,
    EMAIL VARCHAR(255) UNIQUE NOT NULL,
    PASSWORD VARCHAR(255),
    EMAIL_VERIFY BOOL DEFAULT FALSE,
    ADMIN BOOL DEFAULT FALSE,
    FIRST_NAME VARCHAR(255),
    LAST_NAME VARCHAR(255),
    DATE_OF_BIRTH DATE,
    MOBILE VARCHAR(255),
    ADDRESS TEXT,
    AVATAR TEXT,
    CREATE_AT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UPDATE_AT DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

测试相关截图

  • Postman请求截图:Postman请求截图
  • 数据库截图:数据库截图

问题原因

你使用的MySQL驱动(大概率是mysql2)在promise模式下执行query方法时,返回的是包含两个元素的数组:第一个元素是查询结果集,第二个是字段元数据。当数据库中没有匹配的邮箱/用户名时,返回的数组结构为[[], fields],此时emailAlreadyExists.length的值是2,大于0,错误触发了“已存在”的提示。

修复方案

修改校验逻辑,提取返回数组中的第一个元素(实际查询结果)来判断长度:

// 邮箱校验逻辑修改
const [emailResult] = await mysqlConnection.query(emailExistQuery, [EMAIL]);
if (emailResult.length > 0) {
  return res.status(400).send("Email already exists");
}

// 用户名校验逻辑修改
const [usernameResult] = await mysqlConnection.query(usernameExistQuery, [USERNAME]);
if (usernameResult.length > 0) {
  return res.status(400).send("Username already exists");
}

额外优化

为提升查询性能,可将校验语句改为仅查询存在性,无需返回所有字段:

SELECT 1 FROM USERS WHERE EMAIL = ? LIMIT 1
SELECT 1 FROM USERS WHERE USERNAME = ? LIMIT 1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 21:14:50