详解 MySQL 的 sql_mode(SQL 模式)
一、sql_mode 核心概念
sql_mode 是 MySQL 中语法校验、数据校验、行为兼容的核心配置,它定义了 MySQL 对 SQL 语法的解析规则、数据有效性的校验标准,以及与其他数据库(如 Oracle、SQL Server)的兼容策略。sql_mode 决定了 MySQL 是 “宽松模式” 还是 “严格模式”,以及支持哪些 SQL 语法、拒绝哪些非法数据。核心作用
- 规范 SQL 语法:限制或支持特定的 SQL 语法(如是否允许非标准标识符引用);
- 数据有效性校验:阻止无效数据插入 / 更新(如非法日期、除以零、字符串截断等);
- 兼容其他数据库:模拟其他数据库的 SQL 行为(如 Oracle 的字符串连接符
||); - 避免歧义行为:明确 SQL 执行逻辑(如分组查询的字段限制)。
二、查看当前 sql_mode
1. 查看会话级 sql_mode(当前连接生效)
SELECT @@SESSION.sql_mode;
-- 或简写
SELECT @@sql_mode;
2. 查看全局级 sql_mode(所有新连接生效)
SELECT @@GLOBAL.sql_mode;
3. 配置文件位置(永久生效)
my.cnf 或 my.ini)中,sql_mode 可通过配置项直接设置(后续详解)。三、修改 sql_mode 的方式
1. 会话级修改(临时生效,重启 / 断开连接失效)
-- 设置会话级 sql_mode(示例:严格模式+分组限制)
SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO';
2. 全局级修改(需重启 MySQL 生效)
FLUSH PRIVILEGES 刷新权限):-- 设置全局级 sql_mode
SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO';-- 刷新权限(无需重启,新连接立即生效)
FLUSH PRIVILEGES;
3. 配置文件修改(永久生效,推荐生产环境)
my.cnf 或 my.ini)中添加 / 修改 sql_mode,重启 MySQL 后永久生效:# Linux/Mac(my.cnf 通常在 /etc/my.cnf 或 /etc/mysql/my.cnf)
# Windows(my.ini 通常在 MySQL 安装目录的 bin 文件夹)
[mysqld]
sql_mode = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
# Linux 重启命令
systemctl restart mysqld
# 或
service mysqld restart# Windows 重启命令(cmd 管理员模式)
net stop mysql
net start mysql
四、常见 sql_mode 取值详解
sql_mode 支持多值组合(用逗号分隔),以下是最常用的模式值,按功能分类说明:1. 严格模式相关(核心推荐生产启用)
| 模式值 | 作用说明 |
|---|---|
STRICT_TRANS_TABLES |
对事务表(如 InnoDB)启用严格模式:
|
STRICT_ALL_TABLES |
对所有表(事务 / 非事务)启用严格模式:
|
示例:严格模式 vs 宽松模式
CREATE TABLE test_strict (id INT,name VARCHAR(5) -- 姓名最长 5 个字符
) ENGINE=InnoDB;
-
宽松模式(未启用
STRICT_TRANS_TABLES):插入超长字符串时,MySQL 自动截断并警告,数据仍写入:sqlINSERT INTO test_strict VALUES (1, 'abcdefgh'); -- 字符串长度 8 > 5 -- 警告:Data truncated for column 'name' at row 1 -- 结果:name 字段值为 'abcde'(截断后) -
严格模式(启用
STRICT_TRANS_TABLES):插入超长字符串直接报错,数据不写入:sqlINSERT INTO test_strict VALUES (1, 'abcdefgh'); -- 报错:Data truncation: Data too long for column 'name' at row 1
2. 数据有效性校验相关
| 模式值 | 作用说明 |
|---|---|
NO_ZERO_IN_DATE |
禁止日期中的 “月 / 日” 为 0(如 '2025-00-10'、'2025-01-00'),严格模式下报错,宽松模式下警告。 |
NO_ZERO_DATE |
禁止插入 “全零日期”('0000-00-00'),严格模式下报错,宽松模式下警告。 |
ERROR_FOR_DIVISION_BY_ZERO |
禁止 “除以零” 操作:
5/0)直接报错;
5.0/0)返回 NULL 并警告(避免完全阻断查询)。 |
NO_AUTO_VALUE_ON_ZERO |
插入自增字段时,禁止 0 作为自增值(仅允许 NULL 或不指定字段,自动生成自增值)。 |
示例:禁止全零日期
NO_ZERO_DATE + 严格模式:INSERT INTO test_date (create_time) VALUES ('0000-00-00');
-- 报错:Invalid datetime value: '0000-00-00' for column 'create_time' at row 1
3. 语法兼容与规范相关
| 模式值 | 作用说明 | ||
|---|---|---|---|
ONLY_FULL_GROUP_BY |
分组查询(GROUP BY)的严格限制:
SELECT 后的字段必须是 GROUP BY 中的字段,或被聚合函数(SUM/AVG/MAX 等)包裹;
|
||
ANSI_QUOTES |
启用后,字符串只能用单引号 ' 包裹,双引号 " 视为标识符(如表名、字段名),兼容 SQL 标准。 |
||
PIPES_AS_CONCAT |
把管道符 ` | 视为字符串连接符(替代CONCAT ()` 函数),兼容 Oracle 语法。 |
|
IGNORE_SPACE |
允许函数名和括号之间有空格(如 SUM (1+2) 等同于 SUM(1+2)),兼容部分数据库语法。 |
||
NO_ENGINE_SUBSTITUTION |
当指定的存储引擎(如 ENGINE=MyISAM)不存在时,直接报错,而非自动替换为默认引擎(如 InnoDB)。 |
示例 1:ONLY_FULL_GROUP_BY(重点)
-
禁用
ONLY_FULL_GROUP_BY(宽松):分组查询允许非分组字段出现在SELECT中,结果可能随机(同一分组下取第一条数据):sqlSELECT name, age FROM user GROUP BY name; -- age 未分组,未聚合 -- 结果:返回每个 name 对应的第一条 age(不确定) -
启用
ONLY_FULL_GROUP_BY(严格):非分组字段必须用聚合函数包裹,否则报错:sql-- 正确:age 用聚合函数 AVG() 包裹 SELECT name, AVG(age) FROM user GROUP BY name;-- 错误:age 未分组且未聚合 SELECT name, age FROM user GROUP BY name; -- 报错:Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.user.age' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
示例 2:PIPES_AS_CONCAT(兼容 Oracle)
PIPES_AS_CONCAT 后:SELECT 'Hello' || ' ' || 'MySQL' AS result; -- 等同于 CONCAT('Hello', ' ', 'MySQL')
-- 结果:result = 'Hello MySQL'
4. 常用模式组合
| 组合模式 | 包含的模式值 | 适用场景 |
|---|---|---|
ANSI |
REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE |
兼容 SQL 标准,适合多数据库迁移 |
TRADITIONAL |
STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION |
“传统严格模式”,模拟严格的数据库行为 |
ALLOW_INVALID_DATES |
仅校验日期格式(如 MM-DD-YYYY),不校验日期有效性(如 2025-02-30 视为有效) |
兼容旧系统的非法日期数据 |
五、MySQL 不同版本的默认 sql_mode
1. MySQL 5.7+(推荐生产版本)
ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION
NO_AUTO_CREATE_USER 在 MySQL 8.0 中被移除,因为 8.0 不再支持 GRANT 语句自动创建用户,必须显式执行 CREATE USER)2. MySQL 8.0+
NO_AUTO_CREATE_USER):ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION
3. MySQL 5.6 及以下
STRICT_*、ONLY_FULL_GROUP_BY 等),容易产生脏数据,不推荐直接使用。六、常见问题与解决方案
1. 报错:this is incompatible with sql_mode=only_full_group_by
原因
SELECT 包含非分组、非聚合字段,违反 ONLY_FULL_GROUP_BY 规则。解决方案
- 优先方案:优化 SQL,将非分组字段用聚合函数(
SUM/AVG/MAX/ANY_VALUE())包裹:sql-- 用 ANY_VALUE() 取任意值(适合非核心字段) SELECT name, ANY_VALUE(age) FROM user GROUP BY name; - 不推荐方案:临时关闭
ONLY_FULL_GROUP_BY(会牺牲数据一致性):sqlSET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));
2. 报错:Invalid datetime value: '0000-00-00'
原因
NO_ZERO_DATE + 严格模式,禁止插入全零日期。解决方案
- 修正数据:将
'0000-00-00'改为合法日期(如'1970-01-01'); - 临时关闭
NO_ZERO_DATE(不推荐生产):sqlSET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'NO_ZERO_DATE', ''));
3. 迁移 Oracle 数据时,|| 无法连接字符串
解决方案
PIPES_AS_CONCAT 模式:SET GLOBAL sql_mode = CONCAT(@@GLOBAL.sql_mode, ',PIPES_AS_CONCAT');
FLUSH PRIVILEGES;
七、生产环境最佳实践
-
启用严格模式组合:推荐配置(兼容 MySQL 5.7/8.0):ini
sql_mode = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"核心目的:阻止无效数据写入,保证数据一致性。 -
避免随意关闭核心模式:如
ONLY_FULL_GROUP_BY、STRICT_TRANS_TABLES等,关闭后可能导致数据歧义或脏数据。 -
开发 / 测试环境与生产保持一致:避免开发环境宽松、生产环境严格导致的 “本地正常,线上报错”。
-
迁移场景按需调整:
- 从 Oracle 迁移:添加
PIPES_AS_CONCAT, ANSI_QUOTES; - 从旧系统迁移(含非法日期):临时关闭
NO_ZERO_IN_DATE, NO_ZERO_DATE,同步后修正数据再启用。
- 从 Oracle 迁移:添加
-
通过配置文件永久设置:避免使用
SET GLOBAL临时修改(MySQL 重启后失效),优先在my.cnf/my.ini中配置。 - 临时设置模式组合: set @@sql_mode = 'ANSI'; 或者 set @@sql_mode = 'TRADITIONAL,STRICT_ALL_TABLES';
总结
sql_mode 是 MySQL 数据质量和语法兼容的核心配置,生产环境建议启用严格模式 + 必要的兼容模式,通过规范 SQL 语法和校验数据有效性,避免脏数据和歧义行为。理解各模式值的作用,结合业务场景(如迁移、旧系统兼容)灵活调整,是 MySQL 运维和开发的关键技能。sql_mode 不包含 STRICT_ALL_TABLES(即不完整套用 TRADITIONAL 组合),本质是 “平衡严格性与兼容性、适配主流场景”;而模式组合(如 TRADITIONAL、ANSI)的核心用处是 “提供预定义的、场景化的配置模板,简化用户选型成本”。一、为什么 MySQL 默认 sql_mode 缺少 TRADITIONAL 中的 STRICT_ALL_TABLES?
STRICT_TRANS_TABLESvsSTRICT_ALL_TABLES的核心差异(之前提到过,这里聚焦 “默认选择逻辑”):STRICT_TRANS_TABLES:仅对 事务表(如 InnoDB) 严格(无效数据报错),对非事务表(如 MyISAM)宽松(仅警告、截断数据);STRICT_ALL_TABLES:对 所有表(事务 / 非事务) 严格(无效数据均报错)。
- MySQL 的 默认存储引擎演变:
- MySQL 5.5 后默认引擎改为
InnoDB(事务表),至今仍是主流; - 早期非事务表(MyISAM)逐渐被淘汰,但仍有旧系统依赖。
- MySQL 5.5 后默认引擎改为
STRICT_ALL_TABLES 的原因的是 “避免过度严格导致的副作用,兼顾主流场景与历史兼容”:1. 主流场景已被 STRICT_TRANS_TABLES 覆盖
InnoDB 事务表,STRICT_TRANS_TABLES 已经能满足 “严格校验数据、阻止脏数据” 的核心需求 —— 事务表支持回滚,一旦数据无效,报错后整个事务回滚,不会出现 “部分数据写入成功、部分失败” 的情况,数据一致性有保障。STRICT_ALL_TABLES 针对的是 非事务表(MyISAM),但这类表现在极少用,没必要为了小众场景让所有用户承担 “过度严格” 的成本。2. STRICT_ALL_TABLES 对非事务表存在 “数据一致性风险”
STRICT_ALL_TABLES,会出现严重问题:
MyISAM 表批量插入 100 条数据,前 99 条有效,第 100 条无效 —— 此时 STRICT_ALL_TABLES 会直接报错,但前 99 条数据已经写入表中(无法回滚),导致 “部分数据成功、部分失败” 的脏数据状态。STRICT_TRANS_TABLES 对非事务表的处理是 “宽松模式(警告 + 截断)”,虽然会允许部分不严重的无效数据(如字符串截断),但避免了 “批量插入中断导致的数据碎片化”—— 这是 MySQL 权衡后的选择:对小众的非事务表,优先保证 “插入不中断”,而非 “绝对严格”。3. 历史兼容:避免升级后旧系统大面积报错
STRICT_ALL_TABLES,这些旧系统升级后会直接大面积报错,迁移成本极高。而 STRICT_TRANS_TABLES 只针对 InnoDB 严格,对旧系统的非事务表影响极小,兼顾了 “逐步收紧严格性” 和 “历史系统兼容”。二、模式组合(如 TRADITIONAL、ANSI)的实际用处是什么?
sql_mode 集合”—— 它不强制用户使用,但能帮用户 “快速选型、减少配置错误”,核心用处有 3 点:1. 简化配置:一键启用 “场景化规则”,不用手动拼接
-- 手动拼接严格模式(容易漏写、写错)
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
TRADITIONAL 组合,一句话就能实现 “近似效果”(官方已帮你拼好核心严格规则):-- 一键启用“传统严格模式”(包含上述所有规则+STRICT_ALL_TABLES)
SET GLOBAL sql_mode = 'TRADITIONAL';
ERROR_FOR_DIVISION_BY_ZERO),降低配置门槛。2. 场景化适配:快速对齐目标行为(兼容其他数据库 / 严格校验)
| 组合模式 | 核心场景 | 解决的问题 | ||
|---|---|---|---|---|
TRADITIONAL |
需要 “极致严格” 的场景(如金融) | 模拟 Oracle/SQL Server 的严格行为,拒绝任何无效数据,适合对数据一致性要求极高的业务 | ||
ANSI |
多数据库迁移(如从 SQL Server 迁移) | 对齐 SQL 标准语法(如双引号当标识符、` | ` 连接字符串),减少 SQL 改写成本 | |
ALLOW_INVALID_DATES |
兼容旧系统非法日期数据 | 只校验日期格式(如 MM-DD-YYYY),不校验有效性(如 2025-02-30),避免旧数据导入报错 |
ANSI + PIPES_AS_CONCAT 组合,就能直接使用 Oracle 的 || 字符串连接语法,不用把所有 a||b 改成 CONCAT(a,b),极大降低迁移成本。3. 统一规范:团队 / 系统间保持一致的 SQL 行为
sql_mode 更权威、更合理。
TRADITIONAL 模式”,就能避免出现 “开发环境用宽松模式、测试环境用严格模式” 的不一致问题,减少 “本地正常、线上报错” 的排查成本。补充:模式组合不是 “固定不变” 的,支持自定义扩展
TRADITIONAL 的严格性,但不想用 STRICT_ALL_TABLES(因为有少量 MyISAM 表),可以这样配置:-- 基于 TRADITIONAL 组合,去掉 STRICT_ALL_TABLES
sql_mode = "TRADITIONAL,STRICT_TRANS_TABLES"
TRADITIONAL 去掉 STRICT_ALL_TABLES,保留其他严格规则)总结
-
默认
sql_mode缺少STRICT_ALL_TABLES的原因:为了 “适配主流 InnoDB 事务表、避免非事务表的数据一致性风险、兼容旧系统”,MySQL 选择了 “适度严格” 的STRICT_TRANS_TABLES,而非 “过度严格” 的STRICT_ALL_TABLES,是平衡后的最优解。 -
模式组合的核心用处:提供 “场景化、预定义的配置模板”,帮用户 简化配置、快速适配业务场景(如迁移、严格校验)、统一环境规范,同时支持自定义扩展,兼顾 “便捷性” 和 “灵活性”。
sql_mode 是 “MySQL 为大多数用户选的最优默认选项”—— 两者互补,用户可根据自身场景(如是否用非事务表、是否需要兼容其他数据库)选择直接用组合模式,或基于默认值微调。相关新闻
字符串函数的运用
<!DOCTYPE html> <html lang="zh - CN"><head><meta charset="UTF - 8"><meta name="viewport" content="width=device-width, initial - scale=1.0&q…
关于字符
char存储的就是字符 比较 ‘0’ 计算-‘0’这是很重要的 最后的结果也一定要取模 int main() { int n;scanf("%d",&n); char g[n+2][20];int found=0; int qq[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4…
云数据仓库十年架构演进与技术革新
本文深入解析某中心云数据仓库服务十年的技术演进历程,涵盖分布式架构设计、存储计算分离、智能自治优化、多数据源集成等核心技术突破,详细介绍了系统如何通过持续创新实现性能提升和成本优化。云数据仓库十年架构演…
最新新闻
程序员高效驾驭大模型的AI导演工作流
1. 项目概述:程序员如何高效驾驭大模型三年前我第一次接触GPT-3时,花了整整8小时才让模型输出符合需求的代码片段。如今通过系统化的方法沉淀,同样的任务只需30分钟就能完成质量更高的交付。这个转变过程让我意识到:掌握大模型就像…
Linux PipeWire深度解析之pw_thread_loop_in_thread调用流程与实战(二十二)
简介: CSDN博客专家、《Android系统多媒体进阶实战》作者 博主新书推荐:《Android系统多媒体进阶实战》🚀 Android Audio工程师专栏地址: Audio工程师进阶系列【原创干货持续更新中……】🚀 Android多媒体专栏地址&a…
白帽SEO服务商平台推荐:白帽技术趋势2026与合规优化机构盘点 - GEORANK
白帽SEO服务商平台推荐:白帽技术趋势2026与合规优化机构盘点• 核心主题:2026白帽SEO六大技术趋势解读+白帽服务商推荐• 趋势洞察:E-E-A-T权威化、AI辅助+人工审核、SEO+GEO双引擎、结构化内容、UX信号、多模态• …
zynq高频小数据量PS闭环的三个实验-第3课:Linux驱动测试
参考 zynq高频小数据量PS闭环的三个实验-第0课:目的和目标 zynq高频小数据量PS闭环的三个实验-第1课:PL搭建 zynq高频小数据量PS闭环的三个实验-第2课:Vitis裸机测试 zynq高频小数据量PS闭环的三个实验-第3课:Linux驱动测试
从传统架构到超融合:深圳联众合18年实战经验,助企业构建稳定、安全、高效的IT基础设施
很多企业的 IT 负责人都有过这样的经历:半夜接到报警电话,核心 ERP 系统因为单点故障宕机,生产线被迫停摆;或者是办公电脑老化严重,维护一台就要花半天时间,员工抱怨连连。更让人头疼的是,随着数…
强化学习核心要素与工程实践指南
1. 强化学习基础概念解析强化学习(Reinforcement Learning)作为机器学习三大分支之一,与监督学习、无监督学习有着本质区别。我第一次接触RL是在开发机械臂控制项目时,传统控制方法遇到瓶颈后转向了这种"试错学习"的方式…
日新闻
从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)
更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…
帝舵佛山**网点地址更新:2026年7月售后热线电话与服务客户指南 - 帝舵中国官方服务中心
帝舵佛山**网点地址已更新,2026年7月起售后热线电话正式启用为400-801-5381,客户指南同步发布。如需售后、维修或咨询服务,请直接拨打该全国统一**热线,服务时间每日8:00至22:00。地址信息详见下文,请按最新公布信…
亨得利盐城维修点在哪里?手表维修保养地址指南**公示(2026年7月最新) - 亨得利官方
亨得利在盐城设有**售后维修服务点,为当地及周边腕表用户提供标准化的保养与维修支持。2026年7月最新公示的全国统一客服热线为400-878-6612,服务时间为每日8:00至22:00,客户拨打时请确认使用本次公布的最新号码。*…
周新闻
2026年7月最新太原百达翡丽官方售后客服电话及服务网点地址查询 - 百达翡丽官方售后中心
2026年7月,百达翡丽在太原的官方售后服务体系完成更新,客户可通过全国统一客服热线与服务网点获得直接、合规的腕表养护与维修支持。所有售后服务均遵循品牌直营标准,覆盖全国范围,客户可选择到店或邮寄方式,但需…
【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC
可视化利器:JConsole、VisualVM、JMC 实战 本文是《JVM调优实战》专栏第 16 讲。 引言 上一讲我们介绍了 JDK 命令行工具箱,它们轻量、快速,但有一个明显的短板:不直观。面对 jstat -gcutil 输出的一行行数字,你能感知 GC 频率,却难以一眼看出内存泄漏的趋势;你能用 js…
什么是PCTFE?医药高端包装的“防潮王牌“材料
——日氟荣高分子材料(上海)有限公司 专业深耕氟材料领域很多人好奇,高端药品包装为什么比普通包装更防潮、更稳定、保质期更长?核心秘密,就藏在一种特种氟材料——PCTFE聚三氟氯乙烯里!作为国内领先的氟材…
月新闻
[C++]内存管理:串顺序存储的内存回收
在串(字符串)的顺序存储中,内存回收的方式取决于字符串的存储方式以及所使用的编程语言和相关库。以下以 C 为例进行说明,因为 C 对内存管理有较为直接的控制。 1. 基于 char 数组的串顺序存储 如果使用普通的 char 数组来存储字…
移动端游戏功耗测试实战:电流、功率、亮度和场景对比
移动端游戏功耗测试:先控制变量,再比较优化是否真的省电 摘要:功耗测试最容易犯的错误,是拿两次不同温度、不同亮度、不同场景的平均功率直接比较。本文给出一套可复现的游戏功耗测试方法,覆盖引擎特性验证、版本回归和黑盒体验测试,并说明如何把功耗与帧率、温控、CPU/G…
足球口袋教练 HarmonyOS 离线应用实战(03/20):ArkUI 首页仪表盘搭建
本文是“足球口袋教练 HarmonyOS 离线应用实战”系列第 3 篇。示例项目是一个 HarmonyOS / ArkTS / ArkUI 编写的离线足球训练助手,围绕真实页面、真实截图和可复现操作展开。 本篇要解决的问题 训练 App 的首页不能只展示欢迎语,它要解决“我现在该点哪…