简介:这份资源是芋道 ruoyi-vue-pro 企业级快速开发平台的数据库脚本合集,面向使用 Spring Boot 与 Vue 前后端分离架构进行中大型系统开发、二次开发及数据库维护的开发者。包内共 34 个文件,以 22 个 zip 压缩包和 12 个 sql 脚本为主,整体约 143.22MB,涵盖 bpm、crm、mall、erp、pay、member、mp、ai 等业务模块的建表与初始化脚本,以及 quartz、jimureport 等配套数据库文件,可用于快速搭建系统框架、理解数据结构与业务逻辑。目前已有 1092 人学习下载。借助这些脚本,读者能对照各模块版本完成数据库初始化、结构比对与迁移备份,为系统维护和二次开发提供可靠的数据层参考。
1. 拿到一份 SQL 脚本,先别急着往库里灌
后台管理系统做二次开发,绕不开一套能直接跑起来的初始化数据。最近拆的这份「宇道 ruoyi-vue-pro 最新最全 SQL」资源,就是干这件事的:它把一套基于 ruoyi-vue-pro 脚手架的后台系统所需的建表语句、字典数据、菜单权限、示例业务数据打包成可直接执行的 SQL 脚本。你拿到手,导入数据库,后端一启动,菜单树、角色权限、系统字典全都在位,不用再对着空库一行行补基础数据。适合两类人:一是刚接手这套脚手架、想先把环境跑通再改业务的新手;二是要基于它做二次开发、需要一份干净基线数据的老手。下面按「这堆 SQL 里有什么 → 怎么灌进去 → 表结构怎么读 → 改的时候注意什么」的顺序拆。
2. 脚本结构与技术栈:这套 SQL 到底铺了哪些表
2.1 从 ruoyi-vue-pro 的模块划分看 SQL 分组
ruoyi-vue-pro 是 ruoyi 的 Vue 前后端分离增强版,后端 Spring Boot + MyBatis-Plus,前端 Vue + Element。它的库不是一张大平表,而是按业务域切成若干模块,SQL 脚本通常也按这个逻辑分组。常见分组是:系统基础(用户、角色、菜单、部门、字典、日志)、基础设施(文件、定时任务、代码生成、数据库文档)、业务示例(比如商城、CRM 之类的演示模块)。你打开脚本,先看注释头,一般会标-- ----------------------------加表名,按前缀就能归类:
| 表前缀 | 归属模块 | 典型表 |
|---|---|---|
system_ | 系统管理 | system_users、system_role、system_menu、system_dict_data |
infra_ | 基础设施 | infra_file、infra_job、infra_codegen_table |
bpm_ | 工作流(若含) | bpm_process_definition、bpm_task |
| 业务前缀 | 演示业务 | 视资源包含的示例模块而定 |
读脚本时先按前缀分组,能快速判断这份资源覆盖到哪一层。如果只有system_和infra_,那是纯脚手架基线;如果还带业务前缀表,说明附了演示数据,跑起来首页就有内容。
2.2 建表语句里的通用字段约定
ruoyi-vue-pro 的表有一套固定字段习惯,读懂了这套约定,后面改表就不容易翻车。几乎每张业务表都带这几个列:
CREATE TABLE `system_users` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID', `username` varchar(30) NOT NULL COMMENT '用户账号', `password` varchar(100) NOT NULL DEFAULT '' COMMENT '密码', `nickname` varchar(30) NOT NULL COMMENT '用户昵称', `dept_id` bigint DEFAULT NULL COMMENT '部门ID', `status` tinyint NOT NULL DEFAULT '0' COMMENT '状态(0正常 1停用)', `creator` varchar(64) DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', PRIMARY KEY (`id`), KEY `idx_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';这段是典型结构,几个点值得说清。creator/updater/create_time/update_time是审计字段,MyBatis-Plus 的自动填充(MetaObjectHandler)会往里写值,所以建表时给了默认值,手工插数据也不会因为非空报错。deleted是逻辑删除标记,bit(1)类型,配合实体上的@TableLogic,查询自动拼deleted = 0。tenant_id是多租户字段,即使你暂时不开多租户,表里也留着,默认 0,后面要开不用改表结构。utf8mb4是必须的,菜单名、昵称里带表情符号不会炸。
2.3 初始化数据部分:菜单、字典、角色权限怎么落库
建表只是骨架,真正让系统「一登录就有菜单」的是初始化数据。脚本后半段通常是INSERT INTO system_menu、system_role、system_role_menu、system_dict_type、system_dict_data这些。菜单表是树形结构,靠parent_id串起来,permission字段存权限标识(如system:user:query),后端@PreAuthorize注解校验的就是这个字符串。角色和菜单是多对多,中间表system_role_menu把角色 ID 和菜单 ID 绑起来。字典是「类型 + 数据项」两级,system_dict_type存类型编码,system_dict_data存具体选项,前端下拉框直接按类型编码拉数据。
-- 菜单示例:一个带权限标识的按钮级菜单 INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `status`) VALUES (1001, '用户查询', 'system:user:query', 3, 1, 1000, '', 0); -- 角色-菜单绑定:把上面这个菜单授给超级管理员角色 INSERT INTO `system_role_menu` (`role_id`, `menu_id`) VALUES (1, 1001);type字段区分菜单层级:1 目录、2 菜单、3 按钮。按钮级菜单不显示在侧边栏,只用于权限校验,所以path留空。sort控制同级排序。改业务时新增一个页面,通常要同时插一条type=2的菜单和若干type=3的按钮权限,再在system_role_menu里授权,少一步前端就看不到或点不动。
3. 把脚本跑起来:导入顺序、字符集与连接配置
3.1 建库与导入的完整命令
导入前先建库,字符集必须和脚本一致,否则中文注释和菜单名会变问号。常见做法是:
# 1. 建库,显式指定字符集和排序规则 mysql -u root -p -e "CREATE DATABASE ruoyi_vue_pro DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" # 2. 导入脚本,注意指定库名 mysql -u root -p ruoyi_vue_pro < ruoyi-vue-pro.sql # 3. 验证表数量和数据量 mysql -u root -p ruoyi_vue_pro -e "SHOW TABLES; SELECT COUNT(*) FROM system_menu;"如果脚本很大(带演示数据时几十 MB),用source在客户端里执行更稳,能看进度和报错行号:
-- 进入 mysql 客户端后 USE ruoyi_vue_pro; SOURCE /path/to/ruoyi-vue-pro.sql;导入顺序上,如果资源拆成多个文件(建表、基础数据、演示数据分开),一定先建表再插数据,否则外键或逻辑关联会断。单文件脚本一般已经排好序,直接整份执行即可。
3.2 后端连接配置要改哪几处
脚本灌完,后端要连上。ruoyi-vue-pro 的配置在application-local.yaml(或application-dev.yaml)里,数据源部分长这样:
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/ruoyi_vue_pro?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver几个参数别漏:serverTimezone=Asia/Shanghai不写,时间字段可能差 8 小时;allowPublicKeyRetrieval=true在 MySQL 8 默认认证插件下不加会连不上;useSSL=false本地开发关掉省事。如果项目开了多租户或 Redis 缓存,还要确认 Redis 配置和租户拦截器开关,否则登录后菜单可能因为租户过滤查不出来。
3.3 启动后验证数据是否真的生效
后端起来后,别只看「启动成功」日志。按这个顺序验:先访问登录接口拿 token,再调/system/menu/list看菜单树是否返回;前端登录后看侧边栏有没有渲染;进「系统管理 → 字典管理」看下拉选项是否正常。如果菜单为空,八成是system_role_menu没绑对角色,或者当前用户角色 ID 和脚本里的不一致。脚本里的超级管理员角色 ID 通常是 1,用户表里system_users的管理员账号密码是加密串,默认密码要看脚本注释或项目文档,别拿明文去试。
4. 核心表结构拆解:菜单树、权限与多租户字段
4.1 菜单树的自关联查询怎么读
菜单表是典型的自关联树,parent_id=0是根。后端一般用递归或一次性查全表再在内存里组树。MyBatis-Plus 场景下常见写法是先查当前用户有权限的菜单 ID 列表,再按parent_id组装:
// 伪代码:按用户查菜单并组树 List<SystemMenuDO> menus = menuMapper.selectListByUserId(userId); // 已按角色过滤 Map<Long, List<SystemMenuDO>> byParent = menus.stream() .collect(Collectors.groupingBy(SystemMenuDO::getParentId)); // 从 parentId=0 开始递归挂子节点 List<SystemMenuDO> tree = buildTree(byParent, 0L);这里的关键是「先过滤再组树」:如果先组全量树再过滤,父节点被过滤掉后子节点会丢。脚本里system_menu的parent_id必须和id对得上,手工插数据时最容易在这里出错——插了个parent_id=1000的菜单,但 1000 那条根本没插,前端这节点就成孤儿,不显示也不报错,排查起来很费劲。
4.2 权限标识与后端注解的对应关系
permission字段是前后端权限的契约。后端接口上写@PreAuthorize("@ss.hasPermission('system:user:create')"),这个字符串必须和system_menu.permission完全一致,包括大小写和冒号分段。前端按钮的v-hasPermi指令也读同一份数据。改业务时新增接口,流程是:先在菜单表插一条type=3的记录,permission填新标识,再给角色授权,最后后端注解引用同一字符串。三步任一不一致,表现就是 403 或按钮不显示。
4.3 多租户字段对 SQL 的影响
tenant_id这个字段在脚本里几乎每张表都有。不开多租户时它恒为 0,不影响使用;一旦开启,MyBatis-Plus 的租户插件会自动在 SQL 里拼tenant_id = ?,你手写的 XML 查询如果没走插件,就会查出跨租户数据。二次开发时如果自己写复杂查询,要么确认走了租户拦截,要么手动带上租户条件。这也是为什么脚本里初始化数据的tenant_id都显式写 0,而不是靠默认值——避免插件开启后老数据查不到。
5. 避坑与常见问题:导入和改造时最容易翻车的几处
5.1 中文变问号或乱码
现象:导入后菜单名、字典项显示成???。原因:建库时没指定utf8mb4,或者客户端连接字符集是latin1。解决:删库重建,显式DEFAULT CHARACTER SET utf8mb4,导入命令加--default-character-set=utf8mb4,连接串里保留characterEncoding=utf8。
5.2 外键或逻辑关联断裂导致启动报错
现象:后端启动时某张表查询报「字段不存在」或关联数据为空。原因:脚本版本和代码版本不匹配,比如代码里实体多了个字段,但 SQL 是旧版没这列。解决:以代码里的实体和 Mapper XML 为准,对比表结构,缺列就ALTER TABLE补上;反过来 SQL 多出的列不影响运行,但建议对齐。
5.3 菜单不显示但接口有返回
现象:登录成功,接口返回了菜单数据,前端侧边栏空白。原因:菜单type或visible字段值不对,或者parent_id指向了不存在的节点。解决:直接查system_menu看根节点parent_id=0的记录是否存在且status=0,再逐层核对子节点的parent_id是否都能在表里找到。
5.4 重复导入导致主键冲突
现象:第二次执行脚本报Duplicate entry。原因:脚本里INSERT没带IGNORE或ON DUPLICATE KEY,表里已有同 ID 数据。解决:要么先DROP DATABASE重建再导,要么把INSERT INTO改成INSERT IGNORE INTO(仅限初始化数据,业务数据慎用)。我一般习惯导入前先确认库是空的,避免半途报错留下脏数据。
5.5 时间字段差 8 小时
现象:创建时间比实际早或晚 8 小时。原因:连接串没配serverTimezone,或数据库服务器时区和应用不一致。解决:连接串加serverTimezone=Asia/Shanghai,同时确认 MySQL 的time_zone参数,两边对齐。
6. 二次开发改造:在基线数据上安全地加表加菜单
拿到这份 SQL 跑通只是起点,真正的工作是在它上面加业务。我的习惯是:任何结构变更都先写增量脚本,不直接改原始 SQL 文件。原始文件当基线存档,新增表、新增菜单、新增字典各写一个V{日期}__xxx.sql,按顺序执行。这样环境重建时可复现,出问题也能定位是哪次变更引入的。
加一张业务表的完整动作分四步。第一步建表,字段沿用creator/create_time/updater/update_time/deleted/tenant_id这套约定,主键bigint AUTO_INCREMENT,字符集utf8mb4。第二步写实体和 Mapper,实体继承项目里的BaseDO,逻辑删除和多租户字段就自动生效。第三步插菜单:一个type=2的页面菜单挂到对应目录下,若干type=3的按钮权限挂到页面菜单下,permission用模块:实体:动作格式。第四步授权,把新菜单 ID 插进system_role_menu,绑到目标角色。
验证方法别靠肉眼点。我一般写一段校验 SQL,跑一遍确认菜单树没有孤儿节点、权限标识没有重复、角色绑定没有指向不存在的菜单:
-- 检查孤儿菜单:parent_id 非 0 但在表里找不到父节点 SELECT m.id, m.name, m.parent_id FROM system_menu m LEFT JOIN system_menu p ON m.parent_id = p.id WHERE m.parent_id <> 0 AND p.id IS NULL; -- 检查重复权限标识 SELECT permission, COUNT(*) c FROM system_menu WHERE permission <> '' GROUP BY permission HAVING c > 1;这两条查出来是空,菜单结构基本就干净了。血泪经验是:有一次图省事直接在生产库手插菜单,parent_id填错一位,前端整个模块消失,日志里一点线索没有,最后靠上面第一条 SQL 才定位到。从那以后我每次加菜单都强制先跑一遍孤儿检查和重复检查,再启动前端验证。希望帮到你。
本文还有配套的精品资源,点击获取