postgersql.sql 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. CREATE DATABASE oj;
  2. -- USE oj;
  3. -- 创建 schema(如果不存在)
  4. CREATE SCHEMA IF NOT EXISTS dev;
  5. -- 删除序列(如果存在)
  6. -- DROP SEQUENCE IF EXISTS dev.user_id_seq;
  7. -- 创建新序列
  8. -- CREATE SEQUENCE dev.user_id_seq
  9. -- START WITH 1
  10. -- INCREMENT BY 1
  11. -- NO MINVALUE
  12. -- NO MAXVALUE
  13. -- CACHE 1;
  14. -- 添加注释
  15. -- COMMENT ON SEQUENCE dev.user_seq IS '用户表ID序列';
  16. DROP TABLE IF EXISTS dev.user;
  17. -- 在 dev schema 下创建用户表
  18. CREATE TABLE dev.user (
  19. id BIGSERIAL PRIMARY KEY,
  20. account VARCHAR(50) NOT NULL UNIQUE,
  21. password VARCHAR(255) NOT NULL,
  22. username VARCHAR(100) NOT NULL,
  23. role VARCHAR(20) NOT NULL DEFAULT 'user' CHECK (role IN ('user', 'coach', 'admin')),
  24. avatar TEXT,
  25. enable INT NOT NULL DEFAULT 1 CHECK (enable IN (0, 1)),
  26. delete_flag INT NOT NULL DEFAULT 0 CHECK (delete_flag IN (0, 1)),
  27. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  28. updated_at TIMESTAMP NOT NULL DEFAULT NOW()
  29. );
  30. -- 添加注释
  31. COMMENT ON TABLE dev.user IS '用户表';
  32. COMMENT ON COLUMN dev.user.id IS '用户ID,自增主键';
  33. COMMENT ON COLUMN dev.user.account IS '账号,唯一';
  34. COMMENT ON COLUMN dev.user.password IS '密码';
  35. COMMENT ON COLUMN dev.user.username IS '用户名';
  36. COMMENT ON COLUMN dev.user.role IS '角色:user-普通用户,coach-教练,admin-管理员';
  37. COMMENT ON COLUMN dev.user.avatar IS '头像URL';
  38. COMMENT ON COLUMN dev.user.enable IS '是否启用';
  39. COMMENT ON COLUMN dev.user.delete_flag IS '删除标记';
  40. COMMENT ON COLUMN dev.user.created_at IS '创建时间';
  41. COMMENT ON COLUMN dev.user.updated_at IS '更新时间';
  42. -- 创建索引
  43. CREATE INDEX idx_user_role ON dev.user(role);
  44. -- 自动刷新 updated_at 的触发器函数
  45. CREATE OR REPLACE FUNCTION set_updated_at()
  46. RETURNS TRIGGER AS $$
  47. BEGIN
  48. NEW.updated_at = NOW();
  49. RETURN NEW;
  50. END;
  51. $$ LANGUAGE plpgsql;
  52. -- 用户表更新时间自动刷新触发器
  53. CREATE TRIGGER trg_user_updated_at
  54. BEFORE UPDATE ON dev.user
  55. FOR EACH ROW EXECUTE FUNCTION set_updated_at();
  56. CREATE INDEX idx_user_enable ON dev.user(enable);
  57. CREATE INDEX idx_user_delete_flag ON dev.user(delete_flag);
  58. -- 题目表
  59. DROP TABLE IF EXISTS dev.problem;
  60. CREATE TABLE dev.problem (
  61. id BIGSERIAL PRIMARY KEY,
  62. title VARCHAR(200) NOT NULL,
  63. description TEXT NOT NULL,
  64. time_limit_ms INT NOT NULL CHECK (time_limit_ms > 0),
  65. memory_limit_mb INT NOT NULL CHECK (memory_limit_mb > 0),
  66. try_count BIGINT NOT NULL DEFAULT 0,
  67. accepted_count BIGINT NOT NULL DEFAULT 0,
  68. is_public SMALLINT NOT NULL DEFAULT 0 CHECK (is_public IN (0, 1)),
  69. difficulty VARCHAR(10) CHECK (difficulty IN ('easy', 'medium', 'hard')),
  70. created_by BIGINT,
  71. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  72. updated_at TIMESTAMP NOT NULL DEFAULT NOW()
  73. );
  74. COMMENT ON TABLE dev.problem IS '题目表';
  75. COMMENT ON COLUMN dev.problem.id IS '题目唯一标识';
  76. COMMENT ON COLUMN dev.problem.title IS '题目标题';
  77. COMMENT ON COLUMN dev.problem.description IS '题目描述';
  78. COMMENT ON COLUMN dev.problem.time_limit_ms IS '时间限制(毫秒)';
  79. COMMENT ON COLUMN dev.problem.memory_limit_mb IS '内存限制(MB)';
  80. COMMENT ON COLUMN dev.problem.try_count IS '总提交次数';
  81. COMMENT ON COLUMN dev.problem.accepted_count IS '通过次数(AC次数)';
  82. COMMENT ON COLUMN dev.problem.is_public IS '是否公开题目,0-未公开,1-公开';
  83. COMMENT ON COLUMN dev.problem.difficulty IS '难度:easy-简单,medium-中等,hard-困难';
  84. COMMENT ON COLUMN dev.problem.created_by IS '创建者ID,逻辑外键,关联用户表';
  85. COMMENT ON COLUMN dev.problem.created_at IS '创建时间';
  86. COMMENT ON COLUMN dev.problem.updated_at IS '更新时间';
  87. -- 题目样例表
  88. DROP TABLE IF EXISTS dev.problem_case;
  89. CREATE TABLE dev.problem_case (
  90. id BIGSERIAL PRIMARY KEY,
  91. problem_id BIGINT NOT NULL,
  92. input TEXT,
  93. output TEXT,
  94. description TEXT,
  95. sort_order INT NOT NULL DEFAULT 0,
  96. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  97. updated_at TIMESTAMP NOT NULL DEFAULT NOW()
  98. );
  99. COMMENT ON TABLE dev.problem_case IS '题目样例表(展示给用户的示例)';
  100. COMMENT ON COLUMN dev.problem_case.id IS '样例唯一标识';
  101. COMMENT ON COLUMN dev.problem_case.problem_id IS '所属题目ID,逻辑外键,关联题目表';
  102. COMMENT ON COLUMN dev.problem_case.input IS '样例输入';
  103. COMMENT ON COLUMN dev.problem_case.output IS '样例输出';
  104. COMMENT ON COLUMN dev.problem_case.description IS '样例说明';
  105. COMMENT ON COLUMN dev.problem_case.sort_order IS '显示顺序';
  106. COMMENT ON COLUMN dev.problem_case.created_at IS '创建时间';
  107. COMMENT ON COLUMN dev.problem_case.updated_at IS '更新时间';
  108. -- 题目评测用例表
  109. DROP TABLE IF EXISTS dev.problem_test;
  110. CREATE TABLE dev.problem_test (
  111. id BIGSERIAL PRIMARY KEY,
  112. problem_id BIGINT NOT NULL,
  113. input TEXT,
  114. output TEXT,
  115. sort_order INT NOT NULL DEFAULT 0,
  116. is_hidden INT NOT NULL DEFAULT 0,
  117. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  118. updated_at TIMESTAMP NOT NULL DEFAULT NOW()
  119. );
  120. COMMENT ON TABLE dev.problem_test IS '题目评测用例表(后台判题用)';
  121. COMMENT ON COLUMN dev.problem_test.id IS '用例唯一标识';
  122. COMMENT ON COLUMN dev.problem_test.problem_id IS '所属题目ID,逻辑外键,关联题目表';
  123. COMMENT ON COLUMN dev.problem_test.input IS '测试输入';
  124. COMMENT ON COLUMN dev.problem_test.output IS '测试输出';
  125. COMMENT ON COLUMN dev.problem_test.sort_order IS '判题顺序';
  126. COMMENT ON COLUMN dev.problem_test.is_hidden IS '是否隐藏用例,0-不隐藏,1-隐藏(不展示给用户)';
  127. COMMENT ON COLUMN dev.problem_test.created_at IS '创建时间';
  128. COMMENT ON COLUMN dev.problem_test.updated_at IS '更新时间';
  129. -- 提交记录表
  130. DROP TABLE IF EXISTS dev.submission;
  131. CREATE TABLE dev.submission (
  132. id BIGSERIAL PRIMARY KEY,
  133. problem_id BIGINT NOT NULL,
  134. user_id BIGINT NOT NULL,
  135. contest_id BIGINT,
  136. code TEXT NOT NULL,
  137. language VARCHAR(20) NOT NULL,
  138. status VARCHAR(20) NOT NULL DEFAULT 'SUBMITTED' CHECK (status IN ('SUBMITTED', 'JUDGING', 'AC', 'WA', 'TLE', 'MLE', 'RE', 'CE')),
  139. judge_detail TEXT,
  140. time_used_ms INT,
  141. memory_used_kb INT,
  142. score INT,
  143. total_test_cases INT NOT NULL DEFAULT 0,
  144. passed_test_cases INT NOT NULL DEFAULT 0,
  145. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  146. updated_at TIMESTAMP NOT NULL DEFAULT NOW()
  147. );
  148. COMMENT ON TABLE dev.submission IS '提交记录表';
  149. COMMENT ON COLUMN dev.submission.id IS '提交唯一标识';
  150. COMMENT ON COLUMN dev.submission.problem_id IS '题目ID,逻辑外键,关联题目表';
  151. COMMENT ON COLUMN dev.submission.user_id IS '提交用户ID,逻辑外键,关联用户表';
  152. COMMENT ON COLUMN dev.submission.contest_id IS '所属比赛ID,逻辑外键,关联比赛表,为空表示非比赛提交';
  153. COMMENT ON COLUMN dev.submission.code IS '提交代码';
  154. COMMENT ON COLUMN dev.submission.language IS '编程语言(c/cpp/java/python等)';
  155. COMMENT ON COLUMN dev.submission.status IS '判题状态:SUBMITTED-提交成功,JUDGING-判题中,AC-全部测试用例通过,WA-输出与预期不符,TLE-运行时间超限,MLE-内存使用超限,RE-运行时错误,CE-编译失败';
  156. COMMENT ON COLUMN dev.submission.judge_detail IS '判题详情(如编译错误输出、失败用例说明等)';
  157. COMMENT ON COLUMN dev.submission.time_used_ms IS '运行耗时(毫秒)';
  158. COMMENT ON COLUMN dev.submission.memory_used_kb IS '内存占用(KB)';
  159. COMMENT ON COLUMN dev.submission.score IS '该题得分(用于比赛)';
  160. COMMENT ON COLUMN dev.submission.total_test_cases IS '总测试用例数';
  161. COMMENT ON COLUMN dev.submission.passed_test_cases IS '通过的测试用例数';
  162. COMMENT ON COLUMN dev.submission.created_at IS '创建时间';
  163. COMMENT ON COLUMN dev.submission.updated_at IS '更新时间';
  164. -- 题目类别表
  165. DROP TABLE IF EXISTS dev.category;
  166. CREATE TABLE dev.category (
  167. id BIGSERIAL PRIMARY KEY,
  168. category_name VARCHAR(50) NOT NULL UNIQUE,
  169. description TEXT,
  170. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  171. updated_at TIMESTAMP NOT NULL DEFAULT NOW()
  172. );
  173. COMMENT ON TABLE dev.category IS '题目类别表(如动态规划、贪心等)';
  174. COMMENT ON COLUMN dev.category.id IS '类别唯一标识';
  175. COMMENT ON COLUMN dev.category.category_name IS '类别名称';
  176. COMMENT ON COLUMN dev.category.description IS '类别描述';
  177. COMMENT ON COLUMN dev.category.created_at IS '创建时间';
  178. COMMENT ON COLUMN dev.category.updated_at IS '更新时间';
  179. -- 题目-类别关联表
  180. DROP TABLE IF EXISTS dev.problem_category_rel;
  181. CREATE TABLE dev.problem_category_rel (
  182. problem_id BIGINT NOT NULL,
  183. category_id BIGINT NOT NULL,
  184. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  185. updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
  186. PRIMARY KEY (problem_id, category_id)
  187. );
  188. COMMENT ON TABLE dev.problem_category_rel IS '题目与类别关联表';
  189. COMMENT ON COLUMN dev.problem_category_rel.problem_id IS '题目ID,逻辑外键,关联题目表';
  190. COMMENT ON COLUMN dev.problem_category_rel.category_id IS '类别ID,逻辑外键,关联类别表';
  191. COMMENT ON COLUMN dev.problem_category_rel.created_at IS '创建时间';
  192. COMMENT ON COLUMN dev.problem_category_rel.updated_at IS '更新时间';
  193. -- 比赛表
  194. DROP TABLE IF EXISTS dev.contest;
  195. CREATE TABLE dev.contest (
  196. id BIGSERIAL PRIMARY KEY,
  197. title VARCHAR(200) NOT NULL,
  198. description TEXT,
  199. type VARCHAR(20) NOT NULL CHECK (type IN ('public', 'private', 'password')),
  200. password VARCHAR(255),
  201. start_datetime TIMESTAMP NOT NULL,
  202. end_datetime TIMESTAMP NOT NULL CHECK (end_datetime > start_datetime),
  203. status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'running', 'ended')),
  204. created_by BIGINT,
  205. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  206. updated_at TIMESTAMP NOT NULL DEFAULT NOW()
  207. );
  208. COMMENT ON TABLE dev.contest IS '比赛表';
  209. COMMENT ON COLUMN dev.contest.id IS '比赛唯一标识';
  210. COMMENT ON COLUMN dev.contest.title IS '比赛标题';
  211. COMMENT ON COLUMN dev.contest.description IS '比赛描述';
  212. COMMENT ON COLUMN dev.contest.type IS '比赛类型:public-公开,private-私有,password-密码访问';
  213. COMMENT ON COLUMN dev.contest.password IS '访问密码(type为password时使用)';
  214. COMMENT ON COLUMN dev.contest.start_datetime IS '开始时间';
  215. COMMENT ON COLUMN dev.contest.end_datetime IS '结束时间';
  216. COMMENT ON COLUMN dev.contest.status IS '状态:pending-未开始,running-进行中,ended-已结束';
  217. COMMENT ON COLUMN dev.contest.created_by IS '创建者ID,逻辑外键,关联用户表(管理员或教练)';
  218. COMMENT ON COLUMN dev.contest.created_at IS '创建时间';
  219. COMMENT ON COLUMN dev.contest.updated_at IS '更新时间';
  220. -- 比赛题目表
  221. DROP TABLE IF EXISTS dev.contest_problem;
  222. CREATE TABLE dev.contest_problem (
  223. contest_id BIGINT NOT NULL,
  224. problem_id BIGINT NOT NULL,
  225. display_order INT NOT NULL,
  226. score INT NOT NULL,
  227. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  228. updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
  229. PRIMARY KEY (contest_id, problem_id)
  230. );
  231. COMMENT ON TABLE dev.contest_problem IS '比赛与题目关联表';
  232. COMMENT ON COLUMN dev.contest_problem.contest_id IS '比赛ID,逻辑外键,关联比赛表';
  233. COMMENT ON COLUMN dev.contest_problem.problem_id IS '题目ID,逻辑外键,关联题目表';
  234. COMMENT ON COLUMN dev.contest_problem.display_order IS '题目在比赛中的显示序号';
  235. COMMENT ON COLUMN dev.contest_problem.score IS '本题分值';
  236. COMMENT ON COLUMN dev.contest_problem.created_at IS '创建时间';
  237. COMMENT ON COLUMN dev.contest_problem.updated_at IS '更新时间';
  238. -- 比赛报名表
  239. DROP TABLE IF EXISTS dev.contest_registration;
  240. CREATE TABLE dev.contest_registration (
  241. id BIGSERIAL PRIMARY KEY,
  242. contest_id BIGINT NOT NULL,
  243. user_id BIGINT NOT NULL,
  244. created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  245. updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
  246. UNIQUE (contest_id, user_id)
  247. );
  248. COMMENT ON TABLE dev.contest_registration IS '比赛报名表';
  249. COMMENT ON COLUMN dev.contest_registration.id IS '报名记录ID';
  250. COMMENT ON COLUMN dev.contest_registration.contest_id IS '比赛ID,逻辑外键,关联比赛表';
  251. COMMENT ON COLUMN dev.contest_registration.user_id IS '报名用户ID,逻辑外键,关联用户表';
  252. COMMENT ON COLUMN dev.contest_registration.created_at IS '创建时间';
  253. COMMENT ON COLUMN dev.contest_registration.updated_at IS '更新时间';
  254. -- 索引
  255. CREATE INDEX idx_problem_created_by ON dev.problem(created_by);
  256. CREATE INDEX idx_problem_is_public ON dev.problem(is_public);
  257. CREATE INDEX idx_problem_case_problem_id ON dev.problem_case(problem_id);
  258. CREATE INDEX idx_problem_test_problem_id ON dev.problem_test(problem_id);
  259. CREATE INDEX idx_submission_problem_id ON dev.submission(problem_id);
  260. CREATE INDEX idx_submission_user_id ON dev.submission(user_id);
  261. CREATE INDEX idx_submission_contest_id ON dev.submission(contest_id);
  262. CREATE INDEX idx_submission_created_at ON dev.submission(created_at);
  263. CREATE INDEX idx_submission_user_problem ON dev.submission(user_id, problem_id);
  264. CREATE INDEX idx_submission_contest_status ON dev.submission(contest_id, status);
  265. CREATE INDEX idx_problem_category_rel_problem_id ON dev.problem_category_rel(problem_id);
  266. CREATE INDEX idx_problem_category_rel_category_id ON dev.problem_category_rel(category_id);
  267. CREATE INDEX idx_contest_status ON dev.contest(status);
  268. CREATE INDEX idx_contest_start_datetime ON dev.contest(start_datetime);
  269. CREATE INDEX idx_contest_problem_contest_id ON dev.contest_problem(contest_id);
  270. CREATE INDEX idx_contest_problem_problem_id ON dev.contest_problem(problem_id);
  271. CREATE INDEX idx_contest_registration_contest_id ON dev.contest_registration(contest_id);
  272. CREATE INDEX idx_contest_registration_user_id ON dev.contest_registration(user_id);
  273. COMMENT ON INDEX idx_problem_created_by IS '题目创建者索引';
  274. COMMENT ON INDEX idx_problem_is_public IS '题目公开状态索引';
  275. COMMENT ON INDEX idx_problem_case_problem_id IS '题目样例题目ID索引';
  276. COMMENT ON INDEX idx_problem_test_problem_id IS '评测用例题目ID索引';
  277. COMMENT ON INDEX idx_submission_problem_id IS '提交记录题目ID索引';
  278. COMMENT ON INDEX idx_submission_user_id IS '提交记录用户ID索引';
  279. COMMENT ON INDEX idx_submission_contest_id IS '提交记录比赛ID索引';
  280. COMMENT ON INDEX idx_submission_created_at IS '提交记录时间索引';
  281. COMMENT ON INDEX idx_submission_user_problem IS '提交记录用户+题目索引';
  282. COMMENT ON INDEX idx_submission_contest_status IS '提交记录比赛+状态索引';
  283. COMMENT ON INDEX idx_problem_category_rel_problem_id IS '题目类别关联题目ID索引';
  284. COMMENT ON INDEX idx_problem_category_rel_category_id IS '题目类别关联类别ID索引';
  285. COMMENT ON INDEX idx_contest_status IS '比赛状态索引';
  286. COMMENT ON INDEX idx_contest_start_datetime IS '比赛开始时间索引';
  287. COMMENT ON INDEX idx_contest_problem_contest_id IS '比赛题目比赛ID索引';
  288. COMMENT ON INDEX idx_contest_problem_problem_id IS '比赛题目题目ID索引';
  289. COMMENT ON INDEX idx_contest_registration_contest_id IS '比赛报名比赛ID索引';
  290. COMMENT ON INDEX idx_contest_registration_user_id IS '比赛报名用户ID索引';