← 项目列表
课程已完成2026年6月

数据库大作业 — 数据库设计与实施

沉浸式剧本杀平台的完整数据库设计——从 E-R 建模到 3NF 规范化,覆盖 10 张业务表、触发器、存储过程、RBAC 权限体系。

数据库E-R图SQL3NFSQLMySQL视图触发器存储过程RBAC
📋 项目概览
技术栈
SQLMySQL视图触发器存储过程RBAC
功能特性
  • 沉浸式剧本平台数据库设计(10 张表)
  • 用户/剧本/角色/线索/打卡点/场次/订单/排班/进度/评价
  • 触发器:订单支付自动更新场次人数 + NPC 排班冲突检测
  • 视图:场次概览 + 剧本评分汇总
  • 存储过程:场次运营报表生成
  • RBAC 四级角色权限体系(游客/NPC/运营/管理员)
还有 2 项
  • 50+ 条测试数据覆盖全部业务场景
  • 复杂查询:嵌套子查询 / EXISTS / GROUP BY HAVING
🚀 在线演示新窗口打开 ↗
💻 核心代码SQL · MySQL · 视图 · 触发器 · 存储过程 · RBAC
sql核心表结构(建表 DDL)大作业二.sql(建表部分) · 69 行

沉浸式剧本平台的核心数据模型,包含用户、剧本、角色、线索、打卡点 5 张主表。

-- =============================================
-- 沉浸式剧本平台 — 核心表结构
-- 作者: Solivagant
-- =============================================

-- 1. 用户表
CREATE TABLE User (
    user_id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    phone VARCHAR(11) NOT NULL UNIQUE,
    nickname VARCHAR(50) NOT NULL,
    role_type TINYINT NOT NULL DEFAULT 0
        COMMENT '0-游客 1-运营 2-NPC 3-管理员',
    status TINYINT NOT NULL DEFAULT 0,
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 2. 剧本表
CREATE TABLE Script (
    script_id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL COMMENT '剧本名称',
    description TEXT,
    difficulty TINYINT NOT NULL DEFAULT 1,
    duration INT NOT NULL COMMENT '时长(分)',
    min_players INT NOT NULL DEFAULT 1,
    max_players INT NOT NULL,
    cover_url VARCHAR(255),
    status TINYINT NOT NULL DEFAULT 0,
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 3. 角色表
CREATE TABLE Role (
    role_id INT AUTO_INCREMENT PRIMARY KEY,
    script_id INT NOT NULL,
    name VARCHAR(50) NOT NULL,
    description TEXT,
    is_key_role TINYINT NOT NULL DEFAULT 0,
    sort_order INT NOT NULL DEFAULT 0,
    FOREIGN KEY (script_id) REFERENCES Script(script_id)
        ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 4. 线索表
CREATE TABLE Clue (
    clue_id INT AUTO_INCREMENT PRIMARY KEY,
    script_id INT NOT NULL,
    name VARCHAR(100) NOT NULL,
    content TEXT NOT NULL,
    clue_type TINYINT NOT NULL DEFAULT 0,
    trigger_type TINYINT NOT NULL DEFAULT 0,
    sequence_num INT NOT NULL,
    FOREIGN KEY (script_id) REFERENCES Script(script_id)
        ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 5. 打卡点表
CREATE TABLE CheckPoint (
    point_id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    latitude DECIMAL(10,7) NOT NULL,
    longitude DECIMAL(10,7) NOT NULL,
    ar_content_url VARCHAR(255),
    binding_clue_id INT,
    is_required TINYINT NOT NULL DEFAULT 0,
    FOREIGN KEY (binding_clue_id) REFERENCES Clue(clue_id)
        ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
sql触发器:订单支付与排班冲突检测大作业二.sql(触发器) · 43 行

两个关键触发器:支付状态变更自动更新场次报名人数,NPC 排班时间冲突检测防止重复调度。

-- 触发器1:订单支付 -> 场次人数自动更新
DELIMITER //
CREATE TRIGGER trg_order_payment_update_session
AFTER UPDATE ON `Order`
FOR EACH ROW
BEGIN
    IF OLD.payment_status = 0 AND NEW.payment_status = 1 THEN
        UPDATE `Session`
        SET current_players = current_players + 1
        WHERE session_id = NEW.session_id;
    END IF;
    IF OLD.payment_status = 1 AND NEW.payment_status = 2 THEN
        UPDATE `Session`
        SET current_players = current_players - 1
        WHERE session_id = NEW.session_id;
    END IF;
END//
DELIMITER ;

-- 触发器2:NPC排班时间冲突检测
DELIMITER //
CREATE TRIGGER trg_npcschedule_conflict_check
BEFORE INSERT ON NpcSchedule
FOR EACH ROW
BEGIN
    DECLARE conflict_count INT;
    SELECT COUNT(*) INTO conflict_count
    FROM NpcSchedule ns
    JOIN `Session` s ON ns.session_id = s.session_id
    JOIN `Session` s_new ON s_new.session_id = NEW.session_id
    WHERE ns.npc_id = NEW.npc_id
      AND ns.schedule_date = NEW.schedule_date
      AND (
          (s.start_time <= s_new.start_time AND s.end_time > s_new.start_time)
          OR
          (s_new.start_time <= s.start_time AND s_new.end_time > s.start_time)
      );
    IF conflict_count > 0 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = '该NPC在此时间段已有排班冲突';
    END IF;
END//
DELIMITER ;
sql存储过程:场次运营报表大作业二.sql(存储过程) · 44 行

按剧本和时间范围生成运营数据,包含总订单数、总收入、逐场次明细、上座率。

DELIMITER //
CREATE PROCEDURE proc_session_report(
    IN p_script_id INT,
    IN p_start_date DATE,
    IN p_end_date DATE
)
BEGIN
    DECLARE v_total_orders INT DEFAULT 0;
    DECLARE v_total_revenue DECIMAL(12,2) DEFAULT 0;

    SELECT COUNT(o.order_id), COALESCE(SUM(o.amount), 0)
    INTO v_total_orders, v_total_revenue
    FROM `Session` se
    LEFT JOIN `Order` o
        ON se.session_id = o.session_id AND o.payment_status = 1
    WHERE (p_script_id IS NULL OR se.script_id = p_script_id)
      AND DATE(se.start_time) BETWEEN p_start_date AND p_end_date;

    -- 汇总输出
    SELECT p_script_id AS script_id,
           p_start_date AS date_from, p_end_date AS date_to,
           v_total_orders AS paid_orders,
           v_total_revenue AS revenue;

    -- 逐场次明细
    SELECT s.name AS script_name, se.session_id,
           se.start_time,
           CONCAT(se.current_players, '/', se.max_players) AS occupancy,
           ROUND(se.current_players / se.max_players * 100, 1) AS rate,
           se.price,
           COUNT(o.order_id) AS order_count,
           COALESCE(SUM(o.amount), 0) AS session_revenue
    FROM `Session` se
    JOIN Script s ON se.script_id = s.script_id
    LEFT JOIN `Order` o
        ON se.session_id = o.session_id AND o.payment_status = 1
    WHERE (p_script_id IS NULL OR se.script_id = p_script_id)
      AND DATE(se.start_time) BETWEEN p_start_date AND p_end_date
    GROUP BY se.session_id
    ORDER BY se.start_time;
END//
DELIMITER ;

-- 调用:CALL proc_session_report(1, '2026-06-01', '2026-06-30');
📁 源文件清单
路径说明行数
大作业二.sql完整数据库设计(建表/视图/触发器/存储过程/权限/测试数据)709
网站智能助手
💬 和我聊聊
🤖
你好呀 👋 有什么想聊的?