Files
agent-skills/skills/g3fo-db-ops/references/DATABASE_UPDATE_AUTOMATION_GUIDE.md
T

31 KiB
Raw Blame History

G3FO 数据库更新自动化流程指南

概述

本文档定义了使用 Cursor 更新 G3FO 项目数据库数据的标准自动化流程。当需要更新数据库时,系统会自动生成 SQL 语句文件并更新到 g3fo-db 仓库中。

目录结构

g3fo-db/
├── common_sql/                    # 通用SQL模板和工具
│   ├── insert_system_route_procedure.sql    # 插入系统路由存储过程
│   ├── create_table_template.sql            # 创建表模板
│   ├── system_code_update_template.sql      # 系统代码更新模板
│   ├── table_change_template.sql            # 表结构变更模板
│   └── DATABASE_UPDATE_AUTOMATION_GUIDE.md  # 本文档
└── update_service_release/         # 版本发布SQL文件夹
    └── pending release {version}/  # 待执行SQL文件夹(最新版本)

一、使用现有模板和工具

1.1 插入系统菜单和路径权限

重要规则:增加菜单和路径权限必须使用 common_sql 文件夹中的存储过程文件。

使用的文件:

  • g3fo-db/common_sql/insert_system_menu_procedure.sql - 插入系统菜单
  • g3fo-db/common_sql/insert_system_route_procedure.sql - 插入系统路由

执行和提交规则:

执行 SQL 阶段

使用 db_ops.py(Python 数据库工具,替代 MCP MySQL)执行 SQL:

  1. 批量执行含 DELIMITER 的存储过程文件:

    • 使用 python scripts/db_ops.py batch_execute --file path/to/file.sql
    • db_ops.py 支持 DELIMITER,可正确解析并执行存储过程
  2. 或使用 call_procedure 调用已存在的存储过程:

    • python scripts/db_ops.py call_procedure InsertSystemMenu --params "..." "..." "..."
  3. 或使用直接的 INSERT/REPLACE 语句:

    • 使用 execute 命令执行 INSERT INTO 或 REPLACE INTO
    • 确保数据与存储过程生成的数据完全一致
  4. 数据一致性要求:

    • 菜单数据必须插入到 m_system_menus 表
    • 路由数据必须插入到 m_system_routes 表
    • 相应的权限记录必须插入到 m_admin_role_rights 或 m_user_role_rights 表
    • 所有数据必须与存储过程生成的数据完全一致

提交到 Git 阶段

必须使用存储过程文件生成的完整 SQL:

  1. 从模板文件复制:

    • 从 g3fo-db/common_sql/insert_system_menu_procedure.sql 复制完整的存储过程定义
    • 或从 g3fo-db/common_sql/insert_system_route_procedure.sql 复制完整的存储过程定义
  2. 添加 CALL 语句:

    • 在文件末尾添加 CALL 语句来调用存储过程
    • 参考 update_service_release/pending release 1.5.1.18 中的文件格式
  3. 文件格式示例:

插入系统菜单:

USE g3fo_base;

-- ===================================================================
-- 存储过程:插入系统菜单数据
-- ... (完整的存储过程定义,从 insert_system_menu_procedure.sql 复制) ...
-- ===================================================================

DROP PROCEDURE IF EXISTS InsertSystemMenu;
DELIMITER $$
CREATE PROCEDURE InsertSystemMenu(...)
BEGIN
    -- ... 存储过程代码 ...
END$$
DELIMITER ;

-- ===================================================================
-- 在这里添加需要插入的菜单
-- ===================================================================

CALL InsertSystemMenu('菜单备注', 'menu-name', 'title_remark', 'ADMIN', NULL, 1);
CALL InsertSystemMenu('菜单备注2', 'menu-name-2', 'title_remark', 'USER', NULL, 1);

插入系统路由:

USE g3fo_base;

-- ===================================================================
-- 存储过程:插入系统路由数据
-- ... (完整的存储过程定义,从 insert_system_route_procedure.sql 复制) ...
-- ===================================================================

DROP PROCEDURE IF EXISTS InsertSystemRoute;
DELIMITER $$
CREATE PROCEDURE InsertSystemRoute(...)
BEGIN
    -- ... 存储过程代码 ...
END$$
DELIMITER ;

-- ===================================================================
-- 在这里添加需要插入的路由
-- ===================================================================

CALL InsertSystemRoute('备注', '/route/path', '标题备注', 'ADMIN');
CALL InsertSystemRoute('备注2', '/route/path2', '标题备注', 'USER');

文件命名规范:

  • 菜单:insert_system_menu_procedure_{序号}.sql
  • 路由:insert_system_route_procedure_{序号}.sql

参考示例:

  • 查看 update_service_release/pending release 1.5.1.18/insert_system_menu_procedure_03.sql 作为参考

参数说明:

InsertSystemMenu 参数:

  • p_remark: 菜单备注(varchar(50))
  • p_menu_name: 菜单名称,唯一标识(varchar(255))
  • p_title_remark: 标题备注(varchar(50))
  • p_menu_type: 菜单类型,'ADMIN' 或 'USER'(char(8))
  • p_description_i18n_id: 描述国际化ID,可选(char(32)),默认为NULL
  • p_active_flag: 激活标志,可选(smallint),默认为1

InsertSystemRoute 参数:

  • p_remark: 备注
  • p_route: 路由地址
  • p_title_remark: 标题备注
  • p_route_type: 路由类型('ADMIN' 或 'USER')

功能:

  • 自动生成ID(菜单从1开始,路由从7000开始)
  • 自动为相应角色模板创建权限记录
  • 自动去重检查

1.2 创建新表

当需要创建新表时,参照 create_table_template.sql 中的格式:

  • 使用 CREATE TABLE IF NOT EXISTS
  • 指定正确的 schema(如 g3fo_trade, g3fo_base 等)
  • 包含必要的字段、索引、注释
  • 使用 ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

1.3 表结构变更

当需要修改表结构时,参照 table_change_template.sql 中的方法:

  • 使用存储过程检查列是否存在
  • 使用 IF EXISTS 进行幂等性检查
  • 执行后删除存储过程

1.4 订单表字段同步规则

重要:当 m_order 表需要增加字段时,以下三个表必须同时增加相同的字段:

  1. m_order_actions - 订单操作表(g3fo_trade schema)
  2. h_order - 订单历史表(g3fo_trade schema)
  3. h_order_actions - 订单操作历史表(g3fo_trade schema)

规则说明:

  • 字段名称必须完全一致
  • 字段类型必须完全一致
  • 字段约束(NULL/NOT NULL、DEFAULT 等)必须完全一致
  • 字段注释必须完全一致
  • 字段位置(AFTER 子句)应保持一致

SQL 生成要求:

  • 使用存储过程进行幂等性检查(参照 table_change_template.sql)
  • 为每个表分别检查字段是否存在,不存在则添加
  • 确保所有四个表的字段变更在同一个 SQL 文件中完成
  • 使用相同的存储过程模式,为每个表创建独立的检查逻辑

SQL 模板示例:

USE g3fo_trade;
DROP PROCEDURE IF EXISTS AddOrderField;
DELIMITER $$
CREATE PROCEDURE AddOrderField()
BEGIN
    -- 为 m_order 表添加字段
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_schema = 'g3fo_trade'
          AND table_name = 'm_order'
          AND column_name = 'new_field'
    ) THEN
        ALTER TABLE `g3fo_trade`.`m_order` 
        ADD COLUMN `new_field` VARCHAR(100) NULL DEFAULT NULL COMMENT '新字段' 
        AFTER `existing_field`;
    END IF;
    
    -- 为 m_order_actions 表添加相同字段
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_schema = 'g3fo_trade'
          AND table_name = 'm_order_actions'
          AND column_name = 'new_field'
    ) THEN
        ALTER TABLE `g3fo_trade`.`m_order_actions` 
        ADD COLUMN `new_field` VARCHAR(100) NULL DEFAULT NULL COMMENT '新字段' 
        AFTER `existing_field`;
    END IF;
    
    -- 为 h_order 表添加相同字段
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_schema = 'g3fo_trade'
          AND table_name = 'h_order'
          AND column_name = 'new_field'
    ) THEN
        ALTER TABLE `g3fo_trade`.`h_order` 
        ADD COLUMN `new_field` VARCHAR(100) NULL DEFAULT NULL COMMENT '新字段' 
        AFTER `existing_field`;
    END IF;
    
    -- 为 h_order_actions 表添加相同字段
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_schema = 'g3fo_trade'
          AND table_name = 'h_order_actions'
          AND column_name = 'new_field'
    ) THEN
        ALTER TABLE `g3fo_trade`.`h_order_actions` 
        ADD COLUMN `new_field` VARCHAR(100) NULL DEFAULT NULL COMMENT '新字段' 
        AFTER `existing_field`;
    END IF;
END$$
DELIMITER ;
CALL AddOrderField();
DROP PROCEDURE IF EXISTS AddOrderField;

注意事项:

  • 所有四个表的字段定义必须完全一致
  • 必须使用幂等性检查,确保 SQL 可以重复执行
  • 字段位置(AFTER 子句)应保持一致,便于维护

二、需要同时更新 m_system_i18n 的表

以下表在更新数据时必须同时更新 m_system_i18n 表:

表名 i18n_id 格式 填充值 说明
m_system_code CODE-{id} 4位数字ID(如 CODE-0404) 系统编码表
m_system_error_message ERR-{id} 错误码ID 系统错误消息表
m_market MKT-{id} 4位数字ID 市场表
m_currency CURR-{code} 货币代码 货币表
m_channel CH-{code} 渠道代码 渠道表
m_exchange EXCH-{code} 交易所代码 交易所表
m_country CNTY-{code} 国家代码 国家表
m_exchange_charge EX_CHARGE-{id} 费用ID 交易所费用表
m_company_charge COM_CHARGE-{id} 费用ID 公司费用表

重要: 所有上述表的插入和更新操作都必须同时更新 m_system_i18n 表,以提供多语言支持。

三、自动化数据插入流程

3.1 流程概述

  1. 用户输入数据 → 2. 生成SQL语句 → 3. 用户确认 → 4. 执行SQL → 5. 确认执行结果 → 6. 询问是否提交到Git → 7. Git操作

3.2 以 m_system_code 为例的详细流程

步骤 1: 请求用户输入

当用户需要更新或增加 m_system_code 的数据时,Cursor 应请求以下信息:

请提供以下数据:
- Code_type: [编码类型]
- Code_value: [编码值]
- Remark: [备注(用于生成多语言描述)]
- Sort: [排序号]

步骤 2: 自动生成SQL

Cursor 自动执行以下操作:

  1. 获取当前最大ID

    SELECT COALESCE(MAX(id), 0) + 1 FROM g3fo_base.m_system_code;
    
  2. 生成 description_i18n_id

    • 格式:CODE-{4位数字ID}
    • 例如:ID=404 → CODE-0404
  3. 根据 remark 生成多语言描述

    • 如果 remark 包含中英文,自动提取
    • 如果没有,使用 remark 作为英文描述
    • 简体中文(sc_description):从 remark 提取或使用中文部分
    • 繁体中文(tc_description):转换简体为繁体
    • 越南语(vn_description):可选,如果用户提供则使用
    • 法语(fr_description):可选
  4. 生成 SQL 语句

    -- 插入 m_system_code
    REPLACE INTO `g3fo_base`.`m_system_code` 
    (`id`, `code_type`, `code_value`, `description_i18n_id`, `remark`, `sort`, `create_by`, `create_on`, `update_by`, `update_on`) 
    VALUES 
    ({new_id}, '{code_type}', '{code_value}', 'CODE-{formatted_id}', '{remark}', {sort}, 'sys', NOW(), 'sys', NOW());
    
    -- 插入 m_system_i18n
    REPLACE INTO `g3fo_base`.`m_system_i18n` 
    (`id`, `en_description`, `sc_description`, `tc_description`, `vn_description`, `fr_description`, `remark`, `create_by`, `create_on`, `update_by`, `update_on`) 
    VALUES 
    ('CODE-{formatted_id}', '{en_description}', '{sc_description}', '{tc_description}', '{vn_description}', '{fr_description}', NULL, 'sys', NOW(), 'sys', NOW());
    

步骤 3: 用户确认

向用户展示生成的 SQL 语句,询问:

已生成以下 SQL 语句,请确认数据是否正确:

[显示SQL语句]

数据是否有问题?(yes/no)

步骤 4: 执行SQL

如果用户确认无误,使用 db_ops.py 执行 SQL 语句:

  1. 在终端执行:python .claude/skills/g3fo-db-ops/scripts/db_ops.py execute "SQL" 或 batch_execute --file path
  2. 默认连接:host 192.168.3.233, user root, password afe123456;可通过 --database g3fo_base 或 g3fo_trade 指定库
  3. 用户可提供不同连接信息时,使用 --host, --port, --user, --password, --database 覆盖
  4. 验证执行结果(JSON 输出中 "success": true)
  5. 如果成功,继续下一步;如果失败,报告错误并停止

步骤 5: 询问是否提交到Git

执行成功后,询问用户:

SQL 执行成功!

是否需要将 SQL 提交到待执行文件夹中?(yes/no)

步骤 6: Git 操作

如果用户确认提交,必须按照以下顺序执行,确保远程仓库和本地数据一致:

  1. 切换到 g3fo-db 目录并拉取最新代码(必须先执行,确保获取最新文件列表)

    cd g3fo-db
    git pull origin main  # 或相应的分支名
    
    • 重要:这一步必须在确定文件夹和生成文件名之前执行
    • 确保获取远程仓库的最新文件列表和更改
    • 如果 pull 失败(如有冲突),报告错误并停止流程
  2. 确定目标文件夹(基于最新拉取的代码)

    • 查找 update_service_release 下最新的 "pending release {version}" 文件夹
    • 如果不存在,需要创建新的文件夹:
      • 查看 update_service_release 下所有版本号文件夹(如 1.5.1.0, 1.5.1.1, 1.5.1.17 等)
      • 找到最大的版本号,新版本号 = 最大版本号 + 0.0.0.1(最后一位递增)
        • 例如:如果最大版本号是 1.5.1.17,新版本号是 1.5.1.18
      • 创建新文件夹:pending release {新版本号}
      • 自动创建 set_version_01.sql 文件(必须在新文件夹中创建):
        • 文件内容格式:
          UPDATE `g3fo_base`.`m_system_setting`
          SET `param_value` = '1.5.1.0 M{版本号最后两位数字}',
              `update_on` = NOW()
          WHERE
              `param_name` = 'base.systemVersion';
          UPDATE `g3fo_base`.`m_system_setting`
          SET `param_value` = '0',
              `update_on` = NOW()
          WHERE
              `param_name` = 'base.patchNo';
          
        • 版本号与 param_value 的对应关系:
          • 版本号 1.5.1.17 → param_value = '1.5.1.0 M17'
          • 版本号 1.5.1.18 → param_value = '1.5.1.0 M18'
          • 版本号 1.5.1.19 → param_value = '1.5.1.0 M19'
          • 版本号 1.5.1.10 → param_value = '1.5.1.0 M10'
          • 规律:提取版本号的最后一部分数字(版本号格式为 X.Y.Z.N,提取 N),格式为 '1.5.1.0 M{N}'
          • 示例:
            • 1.5.1.17 → 提取 17 → '1.5.1.0 M17'
            • 1.5.1.18 → 提取 18 → '1.5.1.0 M18'
            • 1.5.1.10 → 提取 10 → '1.5.1.0 M10'
            • 1.5.1.9 → 提取 9 → '1.5.1.0 M9'(不补零,保持原数字)
    • 注意:此时文件夹列表是最新的,避免文件名冲突
  3. 生成文件名(基于最新的文件列表)

    • 格式:{功能描述英文}_{序号}.sql
    • 序号规则:
      • 必须在 git pull 之后执行,查看目标文件夹中已有的 SQL 文件(基于最新拉取的代码)
      • 跨所有文件统一计算序号,不区分文件名前缀
      • 提取序号方法:
        1. 遍历文件夹中所有 .sql 文件
        2. 从每个文件名中提取下划线 _ 后面的两位数字(格式:_XX.sql)
        3. 例如:set_version_01.sql → 提取 01,add_system_code_02.sql → 提取 02
        4. 找到所有序号中的最大值
        5. 新序号 = 最大序号 + 1
      • 使用两位数字格式(01, 02, ..., 99)
    • 示例:
      • 如果文件夹中有:set_version_01.sql 和 add_system_code_02.sql
      • 提取的序号:01, 02
      • 最大序号:02
      • 新文件序号:03
      • 新文件名:add_new_feature_03.sql
    • 重要:确保序号不重复,必须基于最新拉取的代码生成
  4. 检测并修复重复序号(在保存文件之前)

    • 扫描目标文件夹中所有 .sql 文件
    • 检测是否有重复序号
    • 如果发现重复,按照"5.4 重复序号检测和自动修复"规则处理
    • 确保所有文件序号唯一且连续
    • 如果进行了修复,生成修复报告并显示给用户
  5. 保存 SQL 文件

    • 将 SQL 语句保存到目标文件夹
    • 文件名使用生成的名称
  6. Git 提交和推送

    git add .
    git commit -m "feat: add system code {code_type} - {code_value}"
    git push origin main  # 或相应的分支名
    

    如果 push 失败(如远程有新的提交):

    • 再次执行 git pull origin main(可能需要处理合并)
    • 解决冲突后重新 push

步骤 7: 完成提示

操作完成!

已执行的操作:
✓ SQL 语句已执行
✓ SQL 文件已保存到: update_service_release/pending release {version}/{filename}
✓ 已推送到 Git 仓库

四、其他表的处理规则

4.1 m_system_error_message

输入数据:

  • Error_code: 错误码(数字)
  • Message_i18n_id: 自动生成 ERR-{error_code}
  • Remark: 英文描述

i18n_id 生成: ERR-{error_code}

SQL 模板:

REPLACE INTO `g3fo_base`.`m_system_error_message` 
(`id`, `error_code`, `message_i18n_id`, `remark`) 
VALUES 
('{error_code}', 'SFO-{error_code}', 'ERR-{error_code}', '{remark}');

REPLACE INTO `g3fo_base`.`m_system_i18n` 
(`id`, `en_description`, `sc_description`, `tc_description`, `vn_description`, `fr_description`, `remark`, `create_by`, `create_on`, `update_by`, `update_on`) 
VALUES 
('ERR-{error_code}', '{en_description}', '{sc_description}', '{tc_description}', '{vn_description}', '{fr_description}', NULL, 'sys', NOW(), 'sys', NOW());

4.2 m_market

输入数据:

  • Market_code: 市场代码
  • Market_name: 市场名称(用于生成i18n)
  • 其他必要字段

i18n_id 生成: MKT-{4位数字ID}(需要先获取最大ID)

4.3 m_currency, m_channel, m_exchange, m_country

输入数据:

  • Code: 代码(用于生成i18n_id)
  • Name: 名称(用于生成i18n)
  • 其他必要字段

i18n_id 生成:

  • Currency: CURR-{currency_code}
  • Channel: CH-{channel_code}
  • Exchange: EXCH-{exchange_code}
  • Country: CNTY-{country_code}

4.4 m_exchange_charge, m_company_charge

输入数据:

  • 相关字段
  • 描述信息(用于生成i18n)

i18n_id 生成:

  • Exchange Charge: EX_CHARGE-{id}
  • Company Charge: COM_CHARGE-{id}

五、文件命名规范

5.1 命名格式

{功能描述英文}_{序号}.sql

5.2 功能描述示例

  • add_system_code - 添加系统代码
  • update_system_code - 更新系统代码
  • add_system_error_message - 添加错误消息
  • insert_system_route - 插入系统路由
  • create_table_{table_name} - 创建表
  • update_table_{table_name}_column - 更新表列
  • add_{table_name}_data - 添加表数据

5.3 序号规则

重要:跨所有文件统一计算序号,不区分文件名前缀

  1. 查看目标文件夹中所有 .sql 文件(基于最新拉取的代码)
  2. 提取序号方法:
    • 遍历所有 .sql 文件
    • 从每个文件名中提取下划线 _ 后面的两位数字(格式:_XX.sql)
    • 例如:
      • set_version_01.sql → 提取 01
      • add_system_code_02.sql → 提取 02
      • update_table_05.sql → 提取 05
  3. 找到所有序号中的最大值
  4. 新文件的序号 = 最大序号 + 1
  5. 使用两位数字格式(01-99)

示例:

  • 如果文件夹中有:set_version_01.sql, add_system_code_02.sql, update_table_05.sql
  • 提取的序号:01, 02, 05
  • 最大序号:05
  • 新文件序号:06
  • 新文件名:add_new_feature_06.sql(不限制文件名前缀)

关键点:

  • 序号是跨所有文件统一计算的,不区分文件名前缀
  • 即使已有 xxxxxx_01.sql,如果最大序号是 01,新文件应该是 xxxxxx_02.sql
  • 如果文件夹中只有 set_version_01.sql,新文件应该是 xxxxxx_02.sql(不是 01)

5.4 重复序号检测和自动修复

重要:在生成新文件或提交到 Git 之前,必须检测并修复重复序号

检测规则

  1. 扫描目标文件夹:检查 update_service_release/pending release {version}/ 文件夹中所有 .sql 文件
  2. 提取序号:从每个文件名中提取下划线 _ 后面的两位数字
  3. 检测重复:如果发现多个文件使用相同的序号,触发修复流程

修复规则

当发现重复序号时(例如:xxxxxx_03.sql 和 aaaaaaa_03.sql),按以下步骤处理:

  1. 分析文件依赖关系:

    • 比对两个文件的 SQL 内容
    • 检查是否存在依赖关系:
      • 文件 A 中引用了文件 B 创建的表、字段、数据等
      • 文件 A 中使用了文件 B 中定义的存储过程、函数等
      • 文件 A 中更新了文件 B 中插入的数据
    • 依赖关系判断方法:
      • 检查 SQL 中的表名、字段名、数据值是否在另一个文件中出现
      • 检查是否有 CREATE/DROP 操作在另一个文件中有对应的引用
      • 检查是否有 INSERT/UPDATE 操作在另一个文件中有对应的查询
      • 检查存储过程、函数的定义和调用关系
  2. 确定文件顺序:

    • 如果有依赖关系:
      • 被依赖的文件(被引用)排在前面,保持原序号
      • 依赖其他文件的排在后面,序号改为下一个可用序号
    • 如果没有依赖关系:
      • 按照文件的创建时间(文件系统时间)确定先后顺序
      • 创建时间较早的文件保持原序号
      • 创建时间较晚的文件序号改为下一个可用序号
  3. 自动顺延后续文件:

    • 找到下一个可用的序号(最大序号 + 1)
    • 将重复序号中需要调整的文件重命名为新序号
    • 检查后续文件是否需要顺延:
      • 如果新序号与后续文件序号冲突,自动顺延后续文件
      • 例如:如果 cccccc_04.sql 和 bbbbbbb_05.sql 存在,且修复后新序号是 04
      • 则 cccccc_04.sql → cccccc_05.sql,bbbbbbb_05.sql → bbbbbbb_06.sql
    • 递归处理,直到没有冲突
  4. 执行修复:

    • 使用 git mv 重命名文件(保持 Git 历史)
    • 更新 Git 索引
    • 生成修复报告,显示所有重命名的文件

修复示例

场景 1:有依赖关系

  • 文件:create_table_03.sql(创建表 m_new_table),insert_data_03.sql(向 m_new_table 插入数据)
  • 检测:insert_data_03.sql 依赖 create_table_03.sql(引用了 m_new_table)
  • 修复:
    • create_table_03.sql 保持 03
    • insert_data_03.sql → insert_data_04.sql

场景 2:无依赖关系,按创建时间

  • 文件:add_system_code_03.sql(创建时间:2024-01-01),update_setting_03.sql(创建时间:2024-01-02)
  • 检测:无依赖关系
  • 修复:
    • add_system_code_03.sql 保持 03(较早)
    • update_setting_03.sql → update_setting_04.sql(较晚)

场景 3:需要顺延后续文件

  • 文件:file_a_03.sql, file_b_03.sql, file_c_04.sql, file_d_05.sql
  • 检测:file_a_03.sql 和 file_b_03.sql 重复,无依赖关系,file_a_03.sql 较早
  • 修复:
    • file_a_03.sql 保持 03
    • file_b_03.sql → file_b_04.sql
    • file_c_04.sql → file_c_05.sql(顺延,因为 04 已被占用)
    • file_d_05.sql → file_d_06.sql(顺延,因为 05 已被占用)

场景 4:多个重复序号

  • 文件:file_a_03.sql, file_b_03.sql, file_c_04.sql, file_d_04.sql, file_e_05.sql
  • 检测:03 重复,04 也重复
  • 修复:
    • 先处理 03 的重复:file_a_03.sql 保持 03,file_b_03.sql → file_b_04.sql
    • 再处理 04 的重复:file_c_04.sql 保持 04,file_d_04.sql → file_d_05.sql
    • 顺延:file_e_05.sql → file_e_06.sql

执行时机

  • 在生成新文件之前:先检测并修复现有文件的重复序号
  • 在提交到 Git 之前:再次检测并修复,确保没有重复序号
  • 可以手动触发:用户要求检测和修复时

修复报告格式

修复完成后,生成报告:

检测到重复序号,已自动修复:

修复的文件:
- file_b_03.sql → file_b_04.sql(原因:与 file_a_03.sql 重复,无依赖关系,按创建时间调整)
- file_c_04.sql → file_c_05.sql(原因:序号冲突,自动顺延)
- file_d_05.sql → file_d_06.sql(原因:序号冲突,自动顺延)

所有文件序号已修复,无重复。

六、SQL 语句规范

6.1 使用 REPLACE INTO

对于数据插入和更新,使用 REPLACE INTO 而不是 INSERT INTO,以确保幂等性:

REPLACE INTO `schema`.`table_name` 
(`column1`, `column2`, ...) 
VALUES 
('value1', 'value2', ...);

6.2 时间戳字段

  • create_on: NOW() 或 CURRENT_TIMESTAMP
  • update_on: NOW() 或 CURRENT_TIMESTAMP
  • create_by: 'sys'(系统操作)或实际用户名
  • update_by: 'sys'(系统操作)或实际用户名

6.3 注释

在 SQL 文件开头添加注释说明:

-- ===================================================================
-- 功能描述:添加系统代码
-- 表名:m_system_code, m_system_i18n
-- 创建时间:{date}
-- ===================================================================

七、Git 操作规范

7.1 操作顺序(重要)

必须严格按照以下顺序执行 Git 操作,确保远程仓库和本地数据一致:

  1. 先执行 git pull - 获取最新代码和文件列表
  2. 然后确定目标文件夹 - 基于最新拉取的代码
  3. 生成文件名 - 基于最新的文件列表,避免序号冲突
  4. 保存文件 - 创建 SQL 文件
  5. 最后执行 git add, commit, push - 提交更改

为什么必须先 pull?

  • 确保获取远程仓库的最新文件列表
  • 避免文件名序号冲突(其他人可能已经添加了新文件)
  • 避免覆盖其他人的更改
  • 确保本地和远程仓库的一致性

7.2 Commit 消息格式

feat: {简短描述}

详细说明(可选)

示例:

  • feat: add system code OrderType - 015
  • feat: add system error message SFO-17100
  • feat: insert system route /trade/order/retryOrder

7.3 分支管理

  • 默认推送到 main 分支
  • 如果项目使用其他分支策略,遵循项目规范

7.4 冲突处理

如果 git pull 时出现冲突:

  1. 报告冲突文件
  2. 询问用户是否手动解决
  3. 或提供解决建议
  4. 不要继续执行后续步骤,直到冲突解决

如果 git push 时失败(远程有新的提交):

  1. 再次执行 git pull origin main(可能需要处理合并)
  2. 解决冲突后重新 push

八、错误处理

8.1 SQL 执行失败

  • 显示错误信息
  • 不执行 Git 操作
  • 询问用户是否重试

8.2 Git 操作失败

  • 显示错误信息
  • SQL 文件已保存到本地
  • 提供手动 Git 操作建议

8.3 数据验证失败

  • 在生成 SQL 前验证数据格式
  • 如果验证失败,提示用户修正

九、重要提醒

9.1 必须同时更新的表

  1. i18n 表更新:所有需要多语言支持的表操作都必须同时更新 m_system_i18n 表
  2. 订单表字段同步:当 m_order 表增加字段时,必须同时在以下三个表中增加相同字段:
    • m_order_actions - 订单操作表
    • h_order - 订单历史表
    • h_order_actions - 订单操作历史表

9.2 菜单和路径权限处理规则

重要:增加菜单和路径权限必须使用存储过程文件

  1. 执行 SQL 阶段:

    • 使用 db_ops.py 的 batch_execute --file 执行含 DELIMITER 的存储过程文件
    • 或使用 call_procedure 调用已存在的存储过程
    • 或使用 execute 配合直接的 INSERT INTO / REPLACE INTO,确保数据与存储过程生成的数据完全一致
  2. 提交到 Git 阶段:

    • 必须使用存储过程文件生成的完整 SQL
    • 从 common_sql 文件夹复制完整的存储过程定义
    • 在文件末尾添加 CALL 语句
    • 参考 update_service_release/pending release 1.5.1.18 中的文件格式

9.3 其他重要规则

  1. 所有 SQL 文件必须保存到正确的版本文件夹中
  2. 文件序号不能重复,必须递增。在生成新文件和提交到 Git 之前,必须检测并修复重复序号
  3. 使用 REPLACE INTO 确保 SQL 可以重复执行
  4. 执行 SQL 前必须获得用户确认
  5. 表结构变更必须使用存储过程进行幂等性检查

十、持续改进

本流程是一个持续更新和改进的流程。在使用过程中,如果发现以下情况,应该更新本文档:

  1. 发现新的需要 i18n 的表
  2. 发现新的需要同步字段的表(如订单表字段同步规则)
  3. 发现新的命名规范或格式要求
  4. 发现流程中的问题或改进点
  5. 添加新的模板或工具

十一、使用示例

示例 1: 添加系统代码

用户输入:

我需要添加一个新的系统代码:
- Code_type: OrderType
- Code_value: 016
- Remark: Market Order (HK)
- Sort: 17

Cursor 处理:

  1. 查询最大ID:假设当前最大ID是 404
  2. 生成新ID:405
  3. 生成 i18n_id:CODE-0405
  4. 生成多语言描述:
    • en: Market Order (HK)
    • sc: 市价单(香港)
    • tc: 市價單(香港)
    • vn: (可选)
  5. 生成 SQL 并展示
  6. 用户确认后执行
  7. 执行成功后询问是否提交到 Git
  8. 如果确认,保存文件并推送到 Git

示例 2: 插入系统路由

用户输入:

我需要添加一个新的系统路由:
- Route: /trade/order/cancel
- Route_type: USER
- Remark: 取消订单
- Title_remark: 订单

Cursor 处理:

  1. 使用 insert_system_route_procedure.sql 模板
  2. 生成 SQL:
    CALL InsertSystemRoute('取消订单', '/trade/order/cancel', '订单', 'USER');
    
  3. 执行并提交到 Git

附录

A. 常用 SQL 查询

获取最大ID:

SELECT COALESCE(MAX(id), 0) + 1 FROM g3fo_base.m_system_code;

检查记录是否存在:

SELECT COUNT(*) FROM g3fo_base.m_system_code 
WHERE code_type = '{code_type}' AND code_value = '{code_value}';

获取当前版本号:

SELECT param_value FROM g3fo_base.m_system_setting 
WHERE param_name = 'base.systemVersion';

B. 多语言描述生成规则

  1. 如果 remark 包含中英文:

    • 提取英文部分作为 en_description
    • 提取中文部分作为 sc_description
    • 转换简体为繁体作为 tc_description
  2. 如果 remark 只有中文:

    • 使用 remark 作为 sc_description 和 tc_description
    • 询问用户英文描述,或使用拼音/音译
  3. 如果 remark 只有英文:

    • 使用 remark 作为 en_description
    • 询问用户中文描述

C. 联系和支持

如有问题或建议,请更新本文档或联系项目维护者。