174 lines
9.0 KiB
SQL
174 lines
9.0 KiB
SQL
-- Unified migration: ctr_customer.area_type -> customer_area and data_area_type -> customer_area.
|
||
-- Target: MySQL 5.7.x; run the whole file against the intended database in one connection.
|
||
-- Confirm both migration_status and dictionary_migration_status report READY.
|
||
-- Conflicting columns or dictionary values are preserved and reported for manual review.
|
||
|
||
SET @customer_table_exists := (
|
||
SELECT COUNT(1) FROM information_schema.TABLES
|
||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer'
|
||
);
|
||
SET @customer_area_old_exists := (
|
||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer' AND COLUMN_NAME = 'area_type'
|
||
);
|
||
SET @customer_area_new_exists := (
|
||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer' AND COLUMN_NAME = 'customer_area'
|
||
);
|
||
SET @customer_area_conflict_count := 0;
|
||
|
||
-- If both columns exist, require matching non-NULL values before merging and dropping the old column.
|
||
SET @customer_area_check_sql := IF(
|
||
@customer_area_old_exists = 1 AND @customer_area_new_exists = 1,
|
||
'SELECT COUNT(1) INTO @customer_area_conflict_count FROM `ctr_customer` WHERE `area_type` IS NOT NULL AND `customer_area` IS NOT NULL AND BINARY `area_type` <> BINARY `customer_area`',
|
||
'SELECT 0 INTO @customer_area_conflict_count'
|
||
);
|
||
PREPARE customer_area_stmt FROM @customer_area_check_sql;
|
||
EXECUTE customer_area_stmt;
|
||
DEALLOCATE PREPARE customer_area_stmt;
|
||
|
||
-- In the no-conflict dual-column state, copy values that only exist in the old column.
|
||
SET @customer_area_merge_sql := IF(
|
||
@customer_area_old_exists = 1 AND @customer_area_new_exists = 1 AND @customer_area_conflict_count = 0,
|
||
'UPDATE `ctr_customer` SET `customer_area` = `area_type` WHERE `customer_area` IS NULL AND `area_type` IS NOT NULL',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE customer_area_stmt FROM @customer_area_merge_sql;
|
||
EXECUTE customer_area_stmt;
|
||
DEALLOCATE PREPARE customer_area_stmt;
|
||
|
||
-- Drop the legacy column only after its values have been merged without conflicts.
|
||
SET @customer_area_drop_sql := IF(
|
||
@customer_area_old_exists = 1 AND @customer_area_new_exists = 1 AND @customer_area_conflict_count = 0,
|
||
'ALTER TABLE `ctr_customer` DROP COLUMN `area_type`',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE customer_area_stmt FROM @customer_area_drop_sql;
|
||
EXECUTE customer_area_stmt;
|
||
DEALLOCATE PREPARE customer_area_stmt;
|
||
|
||
-- Rename the existing column, or create the new column when neither name exists.
|
||
SET @customer_area_rename_sql := CASE
|
||
WHEN @customer_table_exists = 1 AND @customer_area_old_exists = 1 AND @customer_area_new_exists = 0 THEN
|
||
'ALTER TABLE `ctr_customer` CHANGE COLUMN `area_type` `customer_area` varchar(32) DEFAULT NULL COMMENT ''客户区域(字典 customer_area)'' AFTER `customer_type`'
|
||
WHEN @customer_table_exists = 1 AND @customer_area_old_exists = 0 AND @customer_area_new_exists = 0 THEN
|
||
'ALTER TABLE `ctr_customer` ADD COLUMN `customer_area` varchar(32) DEFAULT NULL COMMENT ''客户区域(字典 customer_area)'' AFTER `customer_type`'
|
||
ELSE 'SELECT 1'
|
||
END;
|
||
PREPARE customer_area_stmt FROM @customer_area_rename_sql;
|
||
EXECUTE customer_area_stmt;
|
||
DEALLOCATE PREPARE customer_area_stmt;
|
||
|
||
SET @customer_area_old_exists := (
|
||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer' AND COLUMN_NAME = 'area_type'
|
||
);
|
||
SET @customer_area_new_exists := (
|
||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer' AND COLUMN_NAME = 'customer_area'
|
||
);
|
||
|
||
SELECT CASE
|
||
WHEN @customer_table_exists = 0 THEN 'ERROR: ctr_customer table does not exist in the selected database'
|
||
WHEN @customer_area_old_exists = 0 AND @customer_area_new_exists = 1 THEN 'READY'
|
||
WHEN @customer_area_conflict_count > 0 THEN 'BLOCKED: resolve conflicting values and rerun this full script'
|
||
ELSE 'ERROR: expected customer_area and no area_type; inspect the table before continuing'
|
||
END AS migration_status,
|
||
@customer_area_conflict_count AS conflicting_rows;
|
||
|
||
SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'ctr_customer'
|
||
AND COLUMN_NAME IN ('area_type', 'customer_area')
|
||
ORDER BY ORDINAL_POSITION;
|
||
|
||
-- When migration_status is BLOCKED, inspect these rows, resolve each value manually, then rerun this file.
|
||
SET @customer_area_conflict_rows_sql := IF(
|
||
@customer_area_conflict_count > 0,
|
||
'SELECT `customer_id`, `customer_code`, `area_type`, `customer_area` FROM `ctr_customer` WHERE `area_type` IS NOT NULL AND `customer_area` IS NOT NULL AND BINARY `area_type` <> BINARY `customer_area` ORDER BY `customer_id`',
|
||
'SELECT ''No conflicting customer area values'' AS conflict_check'
|
||
);
|
||
PREPARE customer_area_stmt FROM @customer_area_conflict_rows_sql;
|
||
EXECUTE customer_area_stmt;
|
||
DEALLOCATE PREPARE customer_area_stmt;
|
||
|
||
-- Rename the dictionary identifier and its values. If both dictionary types already exist,
|
||
-- or both dictionaries use the same value, stop and report instead of creating ambiguity.
|
||
SET @customer_area_old_dict_exists := (
|
||
SELECT COUNT(1) FROM `sys_dict_type` WHERE `dict_type` = 'data_area_type'
|
||
);
|
||
SET @customer_area_new_dict_exists := (
|
||
SELECT COUNT(1) FROM `sys_dict_type` WHERE `dict_type` = 'customer_area'
|
||
);
|
||
SET @customer_area_dict_value_conflicts := (
|
||
SELECT COUNT(1)
|
||
FROM `sys_dict_data` old_data
|
||
JOIN `sys_dict_data` new_data ON old_data.`dict_value` = new_data.`dict_value`
|
||
WHERE old_data.`dict_type` = 'data_area_type'
|
||
AND new_data.`dict_type` = 'customer_area'
|
||
);
|
||
|
||
SET @customer_area_dict_data_sql := IF(
|
||
@customer_area_old_exists = 0 AND @customer_area_new_exists = 1
|
||
AND (@customer_area_old_dict_exists = 1 OR @customer_area_new_dict_exists = 1)
|
||
AND @customer_area_dict_value_conflicts = 0
|
||
AND NOT (@customer_area_old_dict_exists = 1 AND @customer_area_new_dict_exists = 1),
|
||
'UPDATE `sys_dict_data` SET `dict_type` = ''customer_area'' WHERE `dict_type` = ''data_area_type''',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE customer_area_stmt FROM @customer_area_dict_data_sql;
|
||
EXECUTE customer_area_stmt;
|
||
DEALLOCATE PREPARE customer_area_stmt;
|
||
|
||
SET @customer_area_dict_type_sql := CASE
|
||
WHEN @customer_area_old_exists = 0 AND @customer_area_new_exists = 1
|
||
AND @customer_area_old_dict_exists = 1 AND @customer_area_new_dict_exists = 0
|
||
AND @customer_area_dict_value_conflicts = 0 THEN
|
||
'UPDATE `sys_dict_type` SET `dict_type` = ''customer_area'', `dict_name` = ''客户区域'', `update_time` = NOW() WHERE `dict_type` = ''data_area_type'''
|
||
WHEN @customer_area_old_exists = 0 AND @customer_area_new_exists = 1
|
||
AND @customer_area_old_dict_exists = 0 AND @customer_area_new_dict_exists = 1
|
||
AND @customer_area_dict_value_conflicts = 0 THEN
|
||
'UPDATE `sys_dict_type` SET `dict_name` = ''客户区域'', `update_time` = NOW() WHERE `dict_type` = ''customer_area'''
|
||
ELSE 'SELECT 1'
|
||
END;
|
||
PREPARE customer_area_stmt FROM @customer_area_dict_type_sql;
|
||
EXECUTE customer_area_stmt;
|
||
DEALLOCATE PREPARE customer_area_stmt;
|
||
|
||
SET @customer_area_old_dict_exists := (
|
||
SELECT COUNT(1) FROM `sys_dict_type` WHERE `dict_type` = 'data_area_type'
|
||
);
|
||
SET @customer_area_new_dict_exists := (
|
||
SELECT COUNT(1) FROM `sys_dict_type` WHERE `dict_type` = 'customer_area'
|
||
);
|
||
|
||
SELECT CASE
|
||
WHEN @customer_area_old_exists <> 0 OR @customer_area_new_exists <> 1 THEN 'BLOCKED: finish customer column migration first'
|
||
WHEN @customer_area_old_dict_exists = 0 AND @customer_area_new_dict_exists = 1
|
||
AND @customer_area_dict_value_conflicts = 0 THEN 'READY'
|
||
WHEN @customer_area_old_dict_exists = 1 AND @customer_area_new_dict_exists = 1 THEN 'BLOCKED: both dictionary types exist; merge them manually'
|
||
WHEN @customer_area_dict_value_conflicts > 0 THEN 'BLOCKED: dictionary values overlap; reconcile them manually'
|
||
ELSE 'MISSING: verify the customer area dictionary in the selected database'
|
||
END AS dictionary_migration_status,
|
||
@customer_area_dict_value_conflicts AS overlapping_values;
|
||
|
||
SELECT `dict_id`, `dict_name`, `dict_type`, `status`
|
||
FROM `sys_dict_type`
|
||
WHERE `dict_type` IN ('data_area_type', 'customer_area')
|
||
ORDER BY `dict_id`;
|
||
|
||
SELECT `dict_code`, `dict_type`, `dict_value`, `dict_label`, `status`
|
||
FROM `sys_dict_data`
|
||
WHERE `dict_type` IN ('data_area_type', 'customer_area')
|
||
ORDER BY `dict_type`, `dict_sort`, `dict_code`;
|
||
|
||
SET @customer_area_dict_conflict_rows_sql := IF(
|
||
@customer_area_dict_value_conflicts > 0,
|
||
'SELECT old_data.`dict_value`, old_data.`dict_label` AS old_label, new_data.`dict_label` AS new_label FROM `sys_dict_data` old_data JOIN `sys_dict_data` new_data ON old_data.`dict_value` = new_data.`dict_value` WHERE old_data.`dict_type` = ''data_area_type'' AND new_data.`dict_type` = ''customer_area'' ORDER BY old_data.`dict_value`',
|
||
'SELECT ''No overlapping dictionary values'' AS conflict_check'
|
||
);
|
||
PREPARE customer_area_stmt FROM @customer_area_dict_conflict_rows_sql;
|
||
EXECUTE customer_area_stmt;
|
||
DEALLOCATE PREPARE customer_area_stmt;
|