-- 1.0.350:统一 S3/S4 MDP 的 tenant_id + factory_id 作用域,并修复贴源表审计字段漂移。 SET NAMES utf8mb4; -- S4 STG:四张活动贴源表补 factory_id;历史数据归入默认工厂 1。 SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_s4_iqc' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `mdp_stg_s4_iqc` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_s4_return' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `mdp_stg_s4_return` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_s4_shipment' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `mdp_stg_s4_shipment` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_s4_shortage' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `mdp_stg_s4_shortage` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- S3 STD / DWD 与 S4 QC DWD:补齐 factory_id,消除中途丢失工厂作用域。 SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_std_delivery_schedule' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `mdp_std_delivery_schedule` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_std_delivery_result' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `mdp_std_delivery_result` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_std_material_readiness' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `mdp_std_material_readiness` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_std_process_outsource_order' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `mdp_std_process_outsource_order` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='dwd_supply_demand' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `dwd_supply_demand` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='dwd_supplier_delivery' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `dwd_supplier_delivery` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='dwd_supplier_risk' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `dwd_supplier_risk` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='dwd_process_outsource_delivery' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `dwd_process_outsource_delivery` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='dwd_material_readiness' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `dwd_material_readiness` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='dwd_material_shortage' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `dwd_material_shortage` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='dwd_qc_trans' AND COLUMN_NAME='factory_id')=0,'ALTER TABLE `dwd_qc_trans` ADD COLUMN `factory_id` BIGINT NOT NULL DEFAULT 1 AFTER `tenant_id`','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 全部 MDP 贴源表必须具备 create_time / update_time;补齐已发现的历史漂移。 SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_external_row' AND COLUMN_NAME='update_time')=0,'ALTER TABLE `mdp_stg_external_row` ADD COLUMN `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_ipqc_inspection' AND COLUMN_NAME='create_time')=0,'ALTER TABLE `mdp_stg_ipqc_inspection` ADD COLUMN `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_ipqc_inspection_detail' AND COLUMN_NAME='create_time')=0,'ALTER TABLE `mdp_stg_ipqc_inspection_detail` ADD COLUMN `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_outsource_issue' AND COLUMN_NAME='create_time')=0,'ALTER TABLE `mdp_stg_outsource_issue` ADD COLUMN `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_outsource_issue_detail' AND COLUMN_NAME='create_time')=0,'ALTER TABLE `mdp_stg_outsource_issue_detail` ADD COLUMN `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_s4_return' AND COLUMN_NAME='create_time')=0,'ALTER TABLE `mdp_stg_s4_return` ADD COLUMN `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @sql := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_stg_s4_shipment' AND COLUMN_NAME='create_time')=0,'ALTER TABLE `mdp_stg_s4_shipment` ADD COLUMN `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP','DO 0'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 历史上该表的唯一键曾被异常启动流程移除,保留重复快照后按更新时间只留最新版本。 CREATE TABLE IF NOT EXISTS `dwd_supplier_delivery_dup_bak_1_0_350` LIKE `dwd_supplier_delivery`; INSERT IGNORE INTO `dwd_supplier_delivery_dup_bak_1_0_350` SELECT old.* FROM `dwd_supplier_delivery` old JOIN `dwd_supplier_delivery` newer ON newer.tenant_id=old.tenant_id AND newer.factory_id=old.factory_id AND newer.po_no=old.po_no AND newer.po_line=old.po_line AND newer.stat_date=old.stat_date AND ( newer.update_time>old.update_time OR (newer.update_time=old.update_time AND newer.calc_time>old.calc_time) OR (newer.update_time=old.update_time AND newer.calc_time=old.calc_time AND newer.id>old.id) ); DELETE old FROM `dwd_supplier_delivery` old JOIN `dwd_supplier_delivery` newer ON newer.tenant_id=old.tenant_id AND newer.factory_id=old.factory_id AND newer.po_no=old.po_no AND newer.po_line=old.po_line AND newer.stat_date=old.stat_date AND ( newer.update_time>old.update_time OR (newer.update_time=old.update_time AND newer.calc_time>old.calc_time) OR (newer.update_time=old.update_time AND newer.calc_time=old.calc_time AND newer.id>old.id) ); -- 唯一键纳入工厂,避免同一租户不同工厂的同业务键互相覆盖。 ALTER TABLE `mdp_stg_s4_iqc` DROP INDEX `uk_mdp_stg_s4_iqc`, ADD UNIQUE INDEX `uk_mdp_stg_s4_iqc` (`tenant_id`,`factory_id`,`source_table`,`source_row_id`), DROP INDEX `uk_source_key`, ADD UNIQUE INDEX `uk_source_key` (`tenant_id`,`factory_id`,`source_system`,`source_table`,`source_biz_key`); ALTER TABLE `mdp_stg_s4_return` DROP INDEX `uk_mdp_stg_s4_return`, ADD UNIQUE INDEX `uk_mdp_stg_s4_return` (`tenant_id`,`factory_id`,`source_table`,`source_row_id`), DROP INDEX `uk_source_key`, ADD UNIQUE INDEX `uk_source_key` (`tenant_id`,`factory_id`,`source_system`,`source_table`,`source_biz_key`); ALTER TABLE `mdp_stg_s4_shipment` DROP INDEX `uk_mdp_stg_s4_shipment`, ADD UNIQUE INDEX `uk_mdp_stg_s4_shipment` (`tenant_id`,`factory_id`,`source_table`,`source_row_id`), DROP INDEX `uk_source_key`, ADD UNIQUE INDEX `uk_source_key` (`tenant_id`,`factory_id`,`source_system`,`source_table`,`source_biz_key`); ALTER TABLE `mdp_stg_s4_shortage` DROP INDEX `uk_mdp_stg_s4_shortage`, ADD UNIQUE INDEX `uk_mdp_stg_s4_shortage` (`tenant_id`,`factory_id`,`source_table`,`source_row_id`), DROP INDEX `uk_source_key`, ADD UNIQUE INDEX `uk_source_key` (`tenant_id`,`factory_id`,`source_system`,`source_table`,`source_biz_key`); ALTER TABLE `mdp_std_delivery_schedule` DROP INDEX `uk_delivery_plan`, ADD UNIQUE INDEX `uk_delivery_plan` (`tenant_id`,`factory_id`,`delivery_plan_no`), DROP INDEX `uk_source_key`, ADD UNIQUE INDEX `uk_source_key` (`tenant_id`,`factory_id`,`source_system`,`source_biz_key`); ALTER TABLE `mdp_std_delivery_result` DROP INDEX `uk_source_key`, ADD UNIQUE INDEX `uk_source_key` (`tenant_id`,`factory_id`,`source_system`,`source_biz_key`); ALTER TABLE `mdp_std_material_readiness` DROP INDEX `uk_source_key`, ADD UNIQUE INDEX `uk_source_key` (`tenant_id`,`factory_id`,`source_system`,`source_biz_key`); ALTER TABLE `mdp_std_process_outsource_order` DROP INDEX `uk_source_key`, ADD UNIQUE INDEX `uk_source_key` (`tenant_id`,`factory_id`,`source_system`,`source_biz_key`); ALTER TABLE `dwd_supply_demand` DROP INDEX `uk_demand_stat`, ADD UNIQUE INDEX `uk_demand_stat` (`tenant_id`,`factory_id`,`stat_date`,`demand_no`,`demand_line`); SET @has_supplier_delivery_uk := ( SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='dwd_supplier_delivery' AND INDEX_NAME='uk_po_line_stat' ); SET @sql := IF( @has_supplier_delivery_uk>0, 'ALTER TABLE `dwd_supplier_delivery` DROP INDEX `uk_po_line_stat`, ADD UNIQUE INDEX `uk_po_line_stat` (`tenant_id`,`factory_id`,`po_no`,`po_line`,`stat_date`)', 'ALTER TABLE `dwd_supplier_delivery` ADD UNIQUE INDEX `uk_po_line_stat` (`tenant_id`,`factory_id`,`po_no`,`po_line`,`stat_date`)' ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; ALTER TABLE `dwd_supplier_risk` DROP INDEX `uk_supplier_risk`, ADD UNIQUE INDEX `uk_supplier_risk` (`tenant_id`,`factory_id`,`stat_date`,`supplier_code`,`item_code`,`risk_type`); CREATE TABLE IF NOT EXISTS `aidop_migration_derived_cleanup_log` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `migration_version` VARCHAR(32) NOT NULL, `table_name` VARCHAR(128) NOT NULL, `estimated_rows` BIGINT NOT NULL DEFAULT 0, `data_length` BIGINT NOT NULL DEFAULT 0, `reason` VARCHAR(500) NOT NULL, `captured_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_migration_cleanup` (`migration_version`,`table_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO `aidop_migration_derived_cleanup_log` (`migration_version`,`table_name`,`estimated_rows`,`data_length`,`reason`) SELECT '1.0.350','dwd_process_outsource_delivery',IFNULL(TABLE_ROWS,0),IFNULL(DATA_LENGTH,0), '历史无作用域重算膨胀约 9628 万行;该表为可重建 DWD,清空后由 tenant+factory 作用域重新生成' FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='dwd_process_outsource_delivery' ON DUPLICATE KEY UPDATE reason=VALUES(reason); TRUNCATE TABLE `dwd_process_outsource_delivery`; ALTER TABLE `dwd_process_outsource_delivery` DROP INDEX `uk_work_op_stat`, ADD UNIQUE INDEX `uk_work_op_stat` (`tenant_id`,`factory_id`,`stat_date`,`work_order`,`op_code`,`po_no`,`po_line`); ALTER TABLE `dwd_material_readiness` DROP INDEX `uk_work_component_stat`, ADD UNIQUE INDEX `uk_work_component_stat` (`tenant_id`,`factory_id`,`stat_date`,`work_order`,`op_code`,`component_item_code`); ALTER TABLE `dwd_qc_trans` DROP INDEX `uk_dwd_qc_trans`, ADD UNIQUE INDEX `uk_dwd_qc_trans` (`tenant_id`,`factory_id`,`trans_date`,`item_code`,`supplier_code`,`batch_no`); CREATE INDEX `idx_mdp_std_delivery_schedule_scope` ON `mdp_std_delivery_schedule` (`tenant_id`,`factory_id`); CREATE INDEX `idx_mdp_std_delivery_result_scope` ON `mdp_std_delivery_result` (`tenant_id`,`factory_id`); CREATE INDEX `idx_mdp_std_material_readiness_scope` ON `mdp_std_material_readiness` (`tenant_id`,`factory_id`); CREATE INDEX `idx_mdp_std_process_outsource_scope` ON `mdp_std_process_outsource_order` (`tenant_id`,`factory_id`); CREATE INDEX `idx_dwd_material_shortage_scope` ON `dwd_material_shortage` (`tenant_id`,`factory_id`);