yanderong
6 天以前 3ad5f38c2f98eb320a1860c51cc5e2c92c7b7469
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
-- 企业优惠快照改造(order库):三张订单表新增「企业优惠方式/折扣率/计费模板」快照列
-- 目的:
--   企业账户(白名单/企业卡/VIN)订单建单时把当时生效的公司优惠设置固化到订单快照列;
--   结算与补偿重算时优先读订单快照(快照为空的历史订单才实时查询并回填),保证:
--     1) 建单后公司优惠设置变更(换折扣率/换模板)不影响历史订单的结算金额与对账口径;
--     2) 方式3(按优惠单价收费)的计费模板被修改/删除时,补偿重算与首次结算口径一致,不降级为原价。
-- 新增列(允许 NULL,历史订单走「实时查询 + 回填」兼容路径):
--   preferential_type           企业优惠方式快照(1=不优惠,2=按比例优惠,3=按优惠单价收费)
--   service_discount_rate       服务费优惠比例快照(%,方式2使用)
--   billing_template_id         计费模板ID快照(方式3使用)
--   billing_template_snapshot   计费模板明细快照JSON(方式3使用,抵抗模板后续变更/删除)
--   preferential_snapshot_time  优惠快照固化时间
-- 创建日期: 2026-09-30
-- 目标库:charging_pile_order
--   分片表:t_charging_order、t_vin_charging_order、t_card_charging_order(Mycat 逻辑表,物理分表逐片执行)
-- 执行方式:
--   1) 首选「小节 A」经数据库代理(MyCat 8066)执行,代理会把 DDL 广播到全部物理分表;
--   2) 代理不支持分片表 DDL 时,改用「小节 B」直连后端 MySQL 实例执行(存储过程,逐物理分表,幂等);
--   3) 最后执行「小节 C」回查校验。
-- 幂等说明:小节 A 为裸 ALTER,重复执行会报 Duplicate column,忽略即可(以小节 C 回查为准);
--           小节 B 先查 information_schema 再变更,可重复执行。
 
-- ============ 小节 A:经代理执行(推荐) ============
USE `charging_pile_order`;
 
ALTER TABLE `t_charging_order`
  ADD COLUMN `preferential_type` tinyint(4) DEFAULT NULL COMMENT '企业优惠方式快照(1=不优惠,2=按比例优惠,3=按优惠单价收费;NULL=建单时未固化)',
  ADD COLUMN `service_discount_rate` decimal(5,2) DEFAULT NULL COMMENT '服务费优惠比例快照(%,方式2使用)',
  ADD COLUMN `billing_template_id` int(11) DEFAULT NULL COMMENT '计费模板ID快照(方式3使用)',
  ADD COLUMN `billing_template_snapshot` text COMMENT '计费模板明细快照JSON(方式3使用,抵抗模板后续变更/删除)',
  ADD COLUMN `preferential_snapshot_time` datetime DEFAULT NULL COMMENT '优惠快照固化时间';
 
ALTER TABLE `t_vin_charging_order`
  ADD COLUMN `preferential_type` tinyint(4) DEFAULT NULL COMMENT '企业优惠方式快照(1=不优惠,2=按比例优惠,3=按优惠单价收费;NULL=建单时未固化)',
  ADD COLUMN `service_discount_rate` decimal(5,2) DEFAULT NULL COMMENT '服务费优惠比例快照(%,方式2使用)',
  ADD COLUMN `billing_template_id` int(11) DEFAULT NULL COMMENT '计费模板ID快照(方式3使用)',
  ADD COLUMN `billing_template_snapshot` text COMMENT '计费模板明细快照JSON(方式3使用,抵抗模板后续变更/删除)',
  ADD COLUMN `preferential_snapshot_time` datetime DEFAULT NULL COMMENT '优惠快照固化时间';
 
ALTER TABLE `t_card_charging_order`
  ADD COLUMN `preferential_type` tinyint(4) DEFAULT NULL COMMENT '企业优惠方式快照(1=不优惠,2=按比例优惠,3=按优惠单价收费;NULL=建单时未固化)',
  ADD COLUMN `service_discount_rate` decimal(5,2) DEFAULT NULL COMMENT '服务费优惠比例快照(%,方式2使用)',
  ADD COLUMN `billing_template_id` int(11) DEFAULT NULL COMMENT '计费模板ID快照(方式3使用)',
  ADD COLUMN `billing_template_snapshot` text COMMENT '计费模板明细快照JSON(方式3使用,抵抗模板后续变更/删除)',
  ADD COLUMN `preferential_snapshot_time` datetime DEFAULT NULL COMMENT '优惠快照固化时间';
 
-- ============ 小节 B:直连后端 MySQL 实例执行(代理不可用时分表执行,幂等) ============
USE `charging_pile_order`;
 
DROP PROCEDURE IF EXISTS `add_company_preferential_snapshot`;
DELIMITER $$
CREATE PROCEDURE `add_company_preferential_snapshot`()
BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE target_table VARCHAR(64);
    DECLARE column_exists INT DEFAULT 0;
 
    -- 覆盖逻辑表(若物理存在)与 TBPARTITION 物理分表
    DECLARE table_cursor CURSOR FOR
        SELECT t.table_name
        FROM information_schema.tables t
        WHERE t.table_schema = DATABASE()
          AND t.table_name REGEXP '^t_charging_order(_[0-9]+)?$|^t_vin_charging_order(_[0-9]+)?$|^t_card_charging_order(_[0-9]+)?$';
 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
 
    OPEN table_cursor;
    table_loop: LOOP
        FETCH table_cursor INTO target_table;
        IF done = 1 THEN
            LEAVE table_loop;
        END IF;
 
        SELECT COUNT(*) INTO column_exists
        FROM information_schema.columns
        WHERE table_schema = DATABASE()
          AND table_name = target_table
          AND column_name = 'preferential_type';
        IF column_exists = 0 THEN
            SET @ddl = CONCAT('ALTER TABLE `', target_table, '` ADD COLUMN `preferential_type` tinyint(4) DEFAULT NULL COMMENT ''企业优惠方式快照(1=不优惠,2=按比例优惠,3=按优惠单价收费;NULL=建单时未固化)''');
            PREPARE stmt FROM @ddl;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
        END IF;
 
        SELECT COUNT(*) INTO column_exists
        FROM information_schema.columns
        WHERE table_schema = DATABASE()
          AND table_name = target_table
          AND column_name = 'service_discount_rate';
        IF column_exists = 0 THEN
            SET @ddl = CONCAT('ALTER TABLE `', target_table, '` ADD COLUMN `service_discount_rate` decimal(5,2) DEFAULT NULL COMMENT ''服务费优惠比例快照(%,方式2使用)''');
            PREPARE stmt FROM @ddl;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
        END IF;
 
        SELECT COUNT(*) INTO column_exists
        FROM information_schema.columns
        WHERE table_schema = DATABASE()
          AND table_name = target_table
          AND column_name = 'billing_template_id';
        IF column_exists = 0 THEN
            SET @ddl = CONCAT('ALTER TABLE `', target_table, '` ADD COLUMN `billing_template_id` int(11) DEFAULT NULL COMMENT ''计费模板ID快照(方式3使用)''');
            PREPARE stmt FROM @ddl;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
        END IF;
 
        SELECT COUNT(*) INTO column_exists
        FROM information_schema.columns
        WHERE table_schema = DATABASE()
          AND table_name = target_table
          AND column_name = 'billing_template_snapshot';
        IF column_exists = 0 THEN
            SET @ddl = CONCAT('ALTER TABLE `', target_table, '` ADD COLUMN `billing_template_snapshot` text COMMENT ''计费模板明细快照JSON(方式3使用,抵抗模板后续变更/删除)''');
            PREPARE stmt FROM @ddl;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
        END IF;
 
        SELECT COUNT(*) INTO column_exists
        FROM information_schema.columns
        WHERE table_schema = DATABASE()
          AND table_name = target_table
          AND column_name = 'preferential_snapshot_time';
        IF column_exists = 0 THEN
            SET @ddl = CONCAT('ALTER TABLE `', target_table, '` ADD COLUMN `preferential_snapshot_time` datetime DEFAULT NULL COMMENT ''优惠快照固化时间''');
            PREPARE stmt FROM @ddl;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
        END IF;
    END LOOP;
    CLOSE table_cursor;
END$$
DELIMITER ;
 
CALL `add_company_preferential_snapshot`();
DROP PROCEDURE IF EXISTS `add_company_preferential_snapshot`;
 
-- ============ 小节 C:回查校验 ============
-- 1) 列存在性与注释(三张订单表均应覆盖逻辑表与全部物理分表):
--    SELECT table_name, column_name, column_type, column_comment
--    FROM information_schema.columns
--    WHERE table_schema = 'charging_pile_order'
--      AND column_name IN ('preferential_type', 'service_discount_rate', 'billing_template_id',
--                          'billing_template_snapshot', 'preferential_snapshot_time')
--    ORDER BY table_name, column_name;
--    预期:三张订单表及各自物理分表均存在 5 列,column_comment 中文无乱码
-- 2) 历史订单快照为空(走实时查询 + 回填兼容路径):
--    SELECT COUNT(*) FROM t_charging_order WHERE preferential_type IS NULL;
--    预期:等于存量订单数