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

求助开发随机不重复答题系统:MySQL记录已答题目逻辑实现

你的答题系统实现方案优化

首先,我得先指出你当前代码里的几个关键问题,这些问题会导致逻辑错误或者安全隐患:


现有代码的核心问题

  • 随机数范围错误:你生成的是1-5的随机数,但你的题库有350道题,应该生成1-350的数
  • 异步逻辑处理不当:con.query是异步操作,但你用了同步的while循环,循环会在数据库查询完成前就执行,导致result的值无法正确判断
  • SQL注入风险:直接把变量x拼到SQL语句里,这是非常危险的做法,容易被注入攻击
  • 循环条件逻辑错误:你初始化result=0,然后循环条件是result >=1,这会导致循环根本不会执行
  • 缺少总题数检查:没有先判断用户是否已经完成了350道题的逻辑

完整的实现方案

我会用Node.js的mysql2库(支持Promise和async/await,比原生mysql库更易维护)来实现,下面是完整的可运行代码:

第一步:安装依赖

先安装mysql2:

npm install mysql2

第二步:实现代码

const mysql = require('mysql2/promise');

// 创建数据库连接池(比单连接更适合高并发场景)
const pool = mysql.createPool({
  host: '你的数据库地址',
  user: '数据库用户名',
  password: '数据库密码',
  database: '数据库名'
});

async function getQuizQuestions(userId) {
  try {
    // 1. 先检查用户已经完成的题目数量
    const [countRows] = await pool.query(
      'SELECT COUNT(*) AS total FROM users WHERE userid = ?',
      [userId]
    );
    const totalCompleted = countRows[0].total;

    // 如果已经完成350道题,返回指定提示
    if (totalCompleted >= 350) {
      return "you have completed the quiz";
    }

    // 2. 获取用户已经答过的所有题号
    const [existingQuestions] = await pool.query(
      'SELECT question FROM users WHERE userid = ?',
      [userId]
    );
    const existingIds = new Set(existingQuestions.map(row => row.question));

    // 3. 生成5个不重复且未答过的随机题号
    const newQuestionIds = [];
    while (newQuestionIds.length < 5) {
      // 生成1-350之间的随机整数
      const randomId = Math.floor(Math.random() * 350) + 1;
      // 确保这个题号既没答过,也不在本次生成的列表里
      if (!existingIds.has(randomId) && !newQuestionIds.includes(randomId)) {
        newQuestionIds.push(randomId);
      }
    }

    // 4. 将新题号插入数据库
    const insertTasks = newQuestionIds.map(id => {
      return pool.query(
        'INSERT INTO users (userid, question) VALUES (?, ?)',
        [userId, id]
      );
    });
    await Promise.all(insertTasks);

    // 返回本次的5道题题号(你可以根据实际需求改成返回题目内容)
    return newQuestionIds;
  } catch (error) {
    console.error('处理答题请求时出错:', error);
    throw error; // 或者根据业务需求处理错误
  }
}

// 示例调用
getQuizQuestions('user_12345')
  .then(result => console.log('本次题目:', result))
  .catch(err => console.error(err));

代码说明

  1. 连接池:使用连接池而不是单连接,能高效处理多个用户的并发请求,避免频繁创建销毁连接的开销
  2. Async/Await:用异步等待的方式编写代码,避免了回调地狱,逻辑更清晰易读
  3. 参数化查询:所有SQL语句都用?作为占位符,然后传入参数数组,彻底避免SQL注入风险
  4. 高效去重:先用Set存储用户已答过的题号(Set的查找是O(1)时间复杂度),生成随机数时直接判断是否在Set里,比多次查询数据库高效得多
  5. 边界处理:先检查用户是否已经完成所有题目,提前返回提示,避免无效操作

可选优化建议

  • 如果你的题库数量可能变化,可以从题目表中动态查询总题数,而不是硬编码350
  • 可以把生成随机题号的逻辑封装成单独的工具函数,提高代码复用性
  • 可以添加事务处理,确保5道题的插入要么全部成功,要么全部失败,避免数据不一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:47:57