liu
4 天以前 5f752161bfa396b80dec6159330d0e0787599a62
docs(sql): 合并版上线迁移脚本改为可重复执行

- 建列/建索引改为 information_schema 判断 + PREPARE 动态执行,已存在则跳过
- 免去上线前人工逐条比对哪些语句需要执行,可整脚本重复执行
- 回填逻辑保持幂等(仅回填 major_category 为空的记录)

Co-Authored-By: Claude <noreply@anthropic.com>
已修改1个文件
69 ■■■■ 文件已修改
doc/20260918_release_report_distinguish_major_category.sql 69 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/20260918_release_report_distinguish_major_category.sql
@@ -1,44 +1,73 @@
-- =============================================================================
-- 上线迁移脚本(合并版)  日期:2026-09-18
-- 上线迁移脚本(合并版·可重复执行)  日期:2026-09-18
-- 用途:生产报工「计数零件分类区分 → 分类进入质检入库」+「报工产品大类」
-- 目标库:MySQL 8.x(在 8.4.7 上验证通过)
--
-- 执行前状态检查(先跑这一段,看清楚哪些还没执行):
--   SELECT TABLE_NAME, COLUMN_NAME FROM information_schema.COLUMNS
--   WHERE TABLE_SCHEMA = DATABASE()
--     AND ((TABLE_NAME = 'production_product_output' AND COLUMN_NAME IN ('rework_minor_qty','rework_major_qty'))
--       OR (TABLE_NAME = 'quality_unqualified'      AND COLUMN_NAME = 'product_main_id')
--       OR (TABLE_NAME = 'production_product_main'  AND COLUMN_NAME = 'major_category'));
--   若查询结果已经包含某列,对应语句就跳过,不要重复执行(MySQL 8 的 ADD COLUMN 不支持 IF NOT EXISTS)。
--
-- 本脚本已做幂等处理:列/索引已存在时自动跳过,可放心重复执行,无需人工判断。
-- 执行顺序:① → ② → ③,全部执行完再发布新版本后端代码,否则接口会因缺列报错。
-- 各环境执行情况:dev(192.168.197.128 / product-inventory-management-tjxm)已执行;
--                测试、生产环境需执行本脚本。
-- 执行顺序:① → ② → ③,全部执行完再发布新版本后端代码,否则接口会因缺列报错。
-- =============================================================================
-- -----------------------------------------------------------------------------
-- ① 报工产出表:增加返工分类数量列(与合格数、报废数一起构成"计数零件的四类区分")
-- -----------------------------------------------------------------------------
ALTER TABLE production_product_output
    ADD COLUMN rework_minor_qty DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '轻微返工数量' AFTER scrap_qty,
    ADD COLUMN rework_major_qty DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT '严重返工数量' AFTER rework_minor_qty;
SET @ddl := (
    SELECT IF(COUNT(*) = 0,
              'ALTER TABLE production_product_output ADD COLUMN rework_minor_qty DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT ''轻微返工数量'' AFTER scrap_qty',
              'SELECT ''rework_minor_qty 已存在,跳过''')
    FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'production_product_output' AND COLUMN_NAME = 'rework_minor_qty'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl := (
    SELECT IF(COUNT(*) = 0,
              'ALTER TABLE production_product_output ADD COLUMN rework_major_qty DECIMAL(18, 4) NOT NULL DEFAULT 0 COMMENT ''严重返工数量'' AFTER rework_minor_qty',
              'SELECT ''rework_major_qty 已存在,跳过''')
    FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'production_product_output' AND COLUMN_NAME = 'rework_major_qty'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- -----------------------------------------------------------------------------
-- ② 不合格品表:增加来源报工单关联列(报工区分出的返工件直接生成待处理单,靠此列回溯报工单)
-- -----------------------------------------------------------------------------
ALTER TABLE quality_unqualified
    ADD COLUMN product_main_id BIGINT DEFAULT NULL COMMENT '关联生产报工主表id' AFTER inspect_id;
SET @ddl := (
    SELECT IF(COUNT(*) = 0,
              'ALTER TABLE quality_unqualified ADD COLUMN product_main_id BIGINT DEFAULT NULL COMMENT ''关联生产报工主表id'' AFTER inspect_id',
              'SELECT ''quality_unqualified.product_main_id 已存在,跳过''')
    FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'quality_unqualified' AND COLUMN_NAME = 'product_main_id'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
CREATE INDEX idx_quality_unqualified_product_main_id ON quality_unqualified (product_main_id);
SET @ddl := (
    SELECT IF(COUNT(*) = 0,
              'CREATE INDEX idx_quality_unqualified_product_main_id ON quality_unqualified (product_main_id)',
              'SELECT ''idx_quality_unqualified_product_main_id 已存在,跳过''')
    FROM information_schema.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'quality_unqualified'
      AND INDEX_NAME = 'idx_quality_unqualified_product_main_id'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- -----------------------------------------------------------------------------
-- ③ 报工主表:增加产品大类列 + 历史数据回填(报工不区分零件,只按小提琴/大提琴/贝斯统计)
-- -----------------------------------------------------------------------------
ALTER TABLE production_product_main
    ADD COLUMN major_category VARCHAR(32) NULL COMMENT '报工产品大类:小提琴/大提琴/贝斯' AFTER product_no;
SET @ddl := (
    SELECT IF(COUNT(*) = 0,
              'ALTER TABLE production_product_main ADD COLUMN major_category VARCHAR(32) NULL COMMENT ''报工产品大类:小提琴/大提琴/贝斯'' AFTER product_no',
              'SELECT ''major_category 已存在,跳过''')
    FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'production_product_main' AND COLUMN_NAME = 'major_category'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 历史数据回填:优先用产出产品自身名称做关键字归类(现场数据"贝斯"写作"贝司"),
-- 未命中再取产品树父节点名称兜底;琴盒/琴套/弓盒等配件先排除避免误归大类;仍无法归类的保持 NULL。
-- 历史数据回填(幂等:仅回填尚未归类的记录):
-- 优先用产出产品自身名称做关键字归类(现场数据"贝斯"写作"贝司"),未命中再取产品树父节点名称兜底;
-- 产品树顶层是"成品/原料"等库存分类,不能直接当大类;琴盒/琴套/弓盒等配件先排除避免误归;
-- 仍无法归类的保持 NULL(如中提琴、红木等原料加工报工)。
UPDATE production_product_main ppm
    JOIN production_product_output ppo ON ppo.production_product_main_id = ppm.id
    JOIN product_model pm ON pm.id = ppo.product_model_id