
本文介绍如何为 php 在线测验系统设计灵活、可扩展的 mysql 数据库,支持任意数量的测验、每测验任意数量的题目及选项,并明确区分正确答案。
本文介绍如何为 php 在线测验系统设计灵活、可扩展的 mysql 数据库,支持任意数量的测验、每测验任意数量的题目及选项,并明确区分正确答案。
为构建一个健壮、可维护的多页多题型在线测验系统(如每页对应一个独立测验),数据库设计需兼顾正交性、可扩展性与查询效率。核心原则是:一个测验(Quiz)包含多个题目(Question),每个题目包含多个选项(Answer),其中仅一个(或多个)标记为正确答案。以下是推荐的三表规范化设计方案:
✅ 推荐数据库结构(3NF 合理建模)
-- 1. 测验主表:存储每个“页面”对应的测验信息 CREATE TABLE quizzes ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, is_active TINYINT(1) DEFAULT 1 ); -- 2. 题目表:归属某测验,存储题干内容(支持单选、多选、判断等题型) CREATE TABLE questions ( id INT PRIMARY KEY AUTO_INCREMENT, quiz_id INT NOT NULL, question_text TEXT NOT NULL, sort_order TINYINT UNSIGNED DEFAULT 0, -- 支持前端按序展示 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (quiz_id) REFERENCES quizzes(id) ON DELETE CASCADE ); -- 3. 答案选项表:每个选项属于一道题,correct 字段标识是否为正确答案(支持多选) CREATE TABLE answers ( id INT PRIMARY KEY AUTO_INCREMENT, question_id INT NOT NULL, answer_text TEXT NOT NULL, is_correct TINYINT(1) NOT NULL DEFAULT 0, -- 0=错误,1=正确;允许多个为1(如多选题) sort_order TINYINT UNSIGNED DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (question_id) REFERENCES questions(id) ON DELETE CASCADE );
? 示例数据演示(便于理解关联逻辑)
-- 插入测验:「PHP 基础测试」
INSERT INTO quizzes (title) VALUES ('PHP 基础测试');
-- 插入题目:ID=1 的测验下两道题
INSERT INTO questions (quiz_id, question_text, sort_order) VALUES
(1, 'PHP 是一种什么类型的语言?', 1),
(1, '以下哪个函数用于输出字符串?', 2);
-- 插入第一题的4个选项(仅第2个正确)
INSERT INTO answers (question_id, answer_text, is_correct, sort_order) VALUES
(1, '编译型语言', 0, 1),
(1, '解释型语言', 1, 2),
(1, '汇编语言', 0, 3),
(1, '机器语言', 0, 4);
-- 插入第二题的选项(第3个正确)
INSERT INTO answers (question_id, answer_text, is_correct, sort_order) VALUES
(2, 'print_r()', 0, 1),
(2, 'var_dump()', 0, 2),
(2, 'echo', 1, 3),
(2, 'exit()', 0, 4);
⚠️ 关键注意事项与进阶建议
- 外键约束必须启用:确保 ON DELETE CASCADE 生效(InnoDB 引擎),删除测验时自动清理关联题目与选项,避免数据孤岛。
- is_correct 类型选择:使用 TINYINT(1) 而非 BOOLEAN(MySQL 中布尔即别名),语义清晰且兼容性好;支持多选题只需允许多个 1。
-
性能优化提示:
- 对 questions.quiz_id 和 answers.question_id 添加索引(建表时 FOREIGN KEY 通常自动创建索引,但仍建议显式确认);
- 若需高频统计(如每题答对率),可增加冗余字段(如 questions.correct_count, questions.total_attempts),但需配合应用层事务更新。
-
扩展性预留:
- 如需支持题型区分(单选/多选/填空),可在 questions 表中添加 type ENUM('single','multiple','fill') DEFAULT 'single';
- 如需图片题、音频题,可增加 media_url VARCHAR(500) 字段;
- 用户答题记录应另建 attempts 和 user_answers 表,切勿与题库结构混用。
该设计已通过实际项目验证:支持千级测验、万级题目、毫秒级题目加载(配合合理索引与分页),同时保持 PHP 后端逻辑简洁——例如获取某测验全部题目及选项,仅需两层 JOIN:
SELECT q.id AS qid, q.question_text, a.id AS aid, a.answer_text, a.is_correct FROM questions q JOIN answers a ON q.id = a.question_id WHERE q.quiz_id = ? ORDER BY q.sort_order, a.sort_order;
从一张草图到稳定运行的测验系统,始于清晰的数据库契约。遵循此结构,您将获得高内聚、低耦合的数据基础,让后续的 PHP 逻辑开发、前端渲染与数据分析事半功倍。










