您的当前位置:首页>全部文章>文章详情

【Webman+MySQL答题系统三】数据库表结构与初始化脚本

果子发表于:2026-10-05 20:55:42浏览:1次TAG: #PHP #MySql #答题系统

本篇目标

把第一篇设计的 6 张表落成 SQL:加索引、灌初始数据,并约定脚本的管理方式。

第三篇封面

一、建表脚本

保存为 database/init.sql,整体执行(MySQL 5.7+,utf8mb4 + InnoDB):

USE quiz_system;

CREATE TABLE `user` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '登录名',
  `password` varchar(100) NOT NULL COMMENT '密码哈希',
  `nickname` varchar(50) NOT NULL DEFAULT '' COMMENT '昵称',
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

CREATE TABLE `question` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `type` tinyint NOT NULL DEFAULT 1 COMMENT '1单选 2多选 3判断',
  `title` varchar(500) NOT NULL COMMENT '题干',
  `options` json NOT NULL COMMENT '选项,如 {"A":"...","B":"..."}',
  `answer` varchar(20) NOT NULL COMMENT '标准答案,逗号分隔',
  `analysis` varchar(500) NOT NULL DEFAULT '' COMMENT '解析',
  `score` decimal(5,1) NOT NULL DEFAULT '2.0' COMMENT '默认分值',
  `status` tinyint NOT NULL DEFAULT 1,
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='题库表';

CREATE TABLE `paper` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `total_score` decimal(6,1) NOT NULL DEFAULT '0' COMMENT '总分',
  `pass_score` decimal(6,1) NOT NULL DEFAULT '60' COMMENT '及格线',
  `duration` int NOT NULL DEFAULT 60 COMMENT '时长(分钟)',
  `status` tinyint NOT NULL DEFAULT 1 COMMENT '1启用 0停用',
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='试卷表';

CREATE TABLE `paper_question` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `paper_id` int unsigned NOT NULL,
  `question_id` int unsigned NOT NULL,
  `sort` int NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_paper_question` (`paper_id`,`question_id`),
  KEY `idx_question` (`question_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='试卷题目关联表';

CREATE TABLE `record` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `paper_id` int unsigned NOT NULL,
  `user_id` int unsigned NOT NULL,
  `score` decimal(6,1) NOT NULL DEFAULT '0',
  `is_pass` tinyint NOT NULL DEFAULT 0,
  `use_seconds` int NOT NULL DEFAULT 0,
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_user` (`user_id`),
  KEY `idx_paper_user` (`paper_id`,`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='答题记录表';

CREATE TABLE `record_answer` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `record_id` int unsigned NOT NULL,
  `question_id` int unsigned NOT NULL,
  `answer` varchar(50) NOT NULL DEFAULT '' COMMENT '用户答案',
  `is_right` tinyint NOT NULL DEFAULT 0,
  `get_score` decimal(5,1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `idx_record` (`record_id`),
  KEY `idx_question` (`question_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='答题明细表';

索引设计说明:uk_paper_question 防止同一题重复入卷;record.idx_paper_user 服务"某人某卷的成绩"高频查询;record_answer.idx_question 服务错题聚合。

二、表关系图

数据库表关系图

paper_question 是典型多对多中间表:一道题可以同时出现在多份卷里,改题一处生效。中间表没有业务主键,靠组合唯一键约束。

三、初始化数据

INSERT INTO `question`(`type`,`title`,`options`,`answer`,`analysis`,`score`) VALUES
(1,'Webman 是基于哪个项目构建的?','{"A":"Symfony","B":"Workerman","C":"ReactPHP","D":"Swoole"}','B','Webman 以 workerman 为内核,保留常驻内存特性。',2),
(2,'下列哪些属于 PHP 常驻内存运行方式?','{"A":"Webman","B":"PHP-FPM 传统模式","C":"Swoole 系框架","D":"Laravel Octane"}','A,C,D','',3),
(3,'Webman 默认监听端口是 8787。','{"A":"对","B":"错"}','A','',1);

INSERT INTO `paper`(`title`,`total_score`,`pass_score`,`duration`) VALUES
('Webman 基础测试卷', 6, 4, 30);

INSERT INTO `paper_question`(`paper_id`,`question_id`,`sort`) VALUES
(1,1,1),(1,2,2),(1,3,3);

用户表密码存哈希,不要手写明文。先生成一个:

php -r "echo password_hash('123456', PASSWORD_DEFAULT);"

把输出粘进去:

INSERT INTO `user`(`username`,`password`,`nickname`) VALUES
('zhangsan', '粘贴上面的哈希', '张三');

四、执行方式

  • 命令行:mysql -uroot -p quiz_system < database/init.sql;
  • 或 Navicat 里直接运行 SQL 文件;
  • init.sql 纳入 Git 版本管理,结构变更走 ALTER 脚本(init_02.sql、init_03.sql 递增),不要回头改老文件——这是多人协作时唯一能追溯历史的方式。

小结

表结构、索引、种子数据全部就位。下一篇开始写业务代码:题目管理的增删改查接口。