Files
zhgh_swufe/scripts/migrate_v3_club_to_v4.sql
T
2026-11-06 13:54:48 +08:00

278 lines
18 KiB
SQL

-- v3 教职工社团数据迁移至 v4。
-- 仅迁移可明确映射的数据;不伪造审核人、审核意见或没有来源的业务字段。
-- 执行要求:指定 zhgh_swufe 为默认库,且 mysql 客户端禁止使用 --force。
USE zhgh_swufe;
SET @migration_time = UNIX_TIMESTAMP() * 1000;
SET @backup_suffix = '20260813_v3_club';
SET @create_backup = (
SELECT CASE WHEN COUNT(*) = 0 THEN 1 ELSE 0 END
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'bak_sys_club_20260813_v3_club'
);
-- 本批次专属备份:保留清理前的业务表、社团角色和对应流程全链路。
CREATE TABLE IF NOT EXISTS bak_sys_club_20260813_v3_club AS SELECT * FROM sys_club WHERE 1 = 0;
INSERT INTO bak_sys_club_20260813_v3_club SELECT * FROM sys_club WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_club_user_20260813_v3_club AS SELECT * FROM club_user WHERE 1 = 0;
INSERT INTO bak_club_user_20260813_v3_club SELECT * FROM club_user WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_club_user_apply_20260813_v3_club AS SELECT * FROM club_user_apply WHERE 1 = 0;
INSERT INTO bak_club_user_apply_20260813_v3_club SELECT * FROM club_user_apply WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_club_pay_record_20260813_v3_club AS SELECT * FROM club_pay_record WHERE 1 = 0;
INSERT INTO bak_club_pay_record_20260813_v3_club SELECT * FROM club_pay_record WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_sponsor_20260813_v3_club AS SELECT * FROM sys_club_sponsor WHERE 1 = 0;
INSERT INTO bak_sys_club_sponsor_20260813_v3_club SELECT * FROM sys_club_sponsor WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_evaluate_20260813_v3_club AS SELECT * FROM sys_club_evaluate WHERE 1 = 0;
INSERT INTO bak_sys_club_evaluate_20260813_v3_club SELECT * FROM sys_club_evaluate WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_examine_register_20260813_v3_club AS SELECT * FROM sys_club_examine_register WHERE 1 = 0;
INSERT INTO bak_sys_club_examine_register_20260813_v3_club SELECT * FROM sys_club_examine_register WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_examine_register_detailed_20260813_v3_club AS SELECT * FROM sys_club_examine_register_detailed WHERE 1 = 0;
INSERT INTO bak_sys_club_examine_register_detailed_20260813_v3_club SELECT * FROM sys_club_examine_register_detailed WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_manager_20260813_v3_club AS SELECT * FROM sys_club_manager WHERE 1 = 0;
INSERT INTO bak_sys_club_manager_20260813_v3_club SELECT * FROM sys_club_manager WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_refresh_20260813_v3_club AS SELECT * FROM sys_club_refresh WHERE 1 = 0;
INSERT INTO bak_sys_club_refresh_20260813_v3_club SELECT * FROM sys_club_refresh WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_rule_20260813_v3_club AS SELECT * FROM sys_club_rule WHERE 1 = 0;
INSERT INTO bak_sys_club_rule_20260813_v3_club SELECT * FROM sys_club_rule WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_user_20260813_v3_club AS SELECT * FROM sys_club_user WHERE 1 = 0;
INSERT INTO bak_sys_club_user_20260813_v3_club SELECT * FROM sys_club_user WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_user_back_history_20260813_v3_club AS SELECT * FROM sys_club_user_back_history WHERE 1 = 0;
INSERT INTO bak_sys_club_user_back_history_20260813_v3_club SELECT * FROM sys_club_user_back_history WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_club_files_20260813_v3_club AS SELECT * FROM sys_club_files WHERE 1 = 0;
INSERT INTO bak_sys_club_files_20260813_v3_club SELECT * FROM sys_club_files WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_sys_user_role_club_20260813_v3_club AS SELECT * FROM sys_user_role WHERE 1 = 0;
INSERT INTO bak_sys_user_role_club_20260813_v3_club SELECT * FROM sys_user_role WHERE NULLIF(TRIM(clubId), '') IS NOT NULL AND @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_wf_process_instance_club_20260813_v3_club AS SELECT i.* FROM wf_process_instance i WHERE 1 = 0;
INSERT INTO bak_wf_process_instance_club_20260813_v3_club
SELECT i.* FROM wf_process_instance i JOIN wf_process_define d ON d.id = i.processDefineId
WHERE d.name IN ('XHZC','XHRH','XHTH','XHPY','XHNS','XHBGLS','XHHJBG','XHZCXD') AND @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_wf_process_task_club_20260813_v3_club AS SELECT * FROM wf_process_task WHERE 1 = 0;
INSERT INTO bak_wf_process_task_club_20260813_v3_club
SELECT t.* FROM wf_process_task t JOIN bak_wf_process_instance_club_20260813_v3_club i ON i.id = t.processInstanceId WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_wf_process_task_actor_club_20260813_v3_club AS SELECT * FROM wf_process_task_actor WHERE 1 = 0;
INSERT INTO bak_wf_process_task_actor_club_20260813_v3_club
SELECT a.* FROM wf_process_task_actor a JOIN bak_wf_process_task_club_20260813_v3_club t ON t.id = a.processTaskId WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_wf_process_cc_instance_club_20260813_v3_club AS SELECT * FROM wf_process_cc_instance WHERE 1 = 0;
INSERT INTO bak_wf_process_cc_instance_club_20260813_v3_club
SELECT c.* FROM wf_process_cc_instance c JOIN bak_wf_process_instance_club_20260813_v3_club i ON i.id = c.processInstanceId WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_outlay_manage_club_refs_20260813_v3_club AS
SELECT o.* FROM outlay_manage_club o JOIN sys_club c ON c.id = o.clubId WHERE @create_backup = 1;
CREATE TABLE IF NOT EXISTS bak_article_club_refs_20260813_v3_club AS
SELECT a.* FROM article a JOIN sys_club c ON c.id = a.clubId WHERE @create_backup = 1;
DROP TEMPORARY TABLE IF EXISTS tmp_club_guard;
CREATE TEMPORARY TABLE tmp_club_guard (name VARCHAR(64), actual BIGINT, expected BIGINT, bad INT AS (actual <> expected) STORED) ENGINE=InnoDB;
INSERT INTO tmp_club_guard(name, actual, expected) SELECT 'source_club_count', COUNT(*), 12 FROM union_swufe.sys_club;
INSERT INTO tmp_club_guard(name, actual, expected) SELECT 'source_valid_member_count', COUNT(*), 14 FROM union_swufe.sys_club_user WHERE clubid IS NOT NULL AND status = 5;
INSERT INTO tmp_club_guard(name, actual, expected) SELECT 'source_sponsor_count', COUNT(*), 2 FROM union_swufe.sys_club_sponsor;
INSERT INTO tmp_club_guard(name, actual, expected)
SELECT 'source_users_missing_v4', COUNT(*), 0
FROM union_swufe.sys_club_user s LEFT JOIN sys_user u
ON CONVERT(u.id USING utf8mb4) = CONVERT(s.userid USING utf8mb4) COLLATE utf8mb4_0900_ai_ci
WHERE s.clubid IS NOT NULL AND s.status = 5 AND u.id IS NULL;
INSERT INTO tmp_club_guard(name, actual, expected)
SELECT 'source_club_contact_missing_v4', COUNT(*), 0
FROM union_swufe.sys_club s LEFT JOIN sys_user u
ON CONVERT(u.id USING utf8mb4) = CONVERT(s.concatPerson USING utf8mb4) COLLATE utf8mb4_0900_ai_ci
WHERE NULLIF(TRIM(s.concatPerson), '') IS NOT NULL AND u.id IS NULL;
DROP TEMPORARY TABLE IF EXISTS tmp_club_guard_fail;
CREATE TEMPORARY TABLE tmp_club_guard_fail(id INT NOT NULL) ENGINE=InnoDB;
INSERT INTO tmp_club_guard_fail SELECT NULL FROM tmp_club_guard WHERE bad = 1 LIMIT 1;
START TRANSACTION;
-- 先删除流程子表,再删除社团业务表,避免残留无主任务和角色关系。
DELETE a FROM wf_process_task_actor a
JOIN wf_process_task t ON t.id = a.processTaskId
JOIN wf_process_instance i ON i.id = t.processInstanceId
JOIN wf_process_define d ON d.id = i.processDefineId
WHERE d.name IN ('XHZC','XHRH','XHTH','XHPY','XHNS','XHBGLS','XHHJBG','XHZCXD');
DELETE c FROM wf_process_cc_instance c
JOIN wf_process_instance i ON i.id = c.processInstanceId
JOIN wf_process_define d ON d.id = i.processDefineId
WHERE d.name IN ('XHZC','XHRH','XHTH','XHPY','XHNS','XHBGLS','XHHJBG','XHZCXD');
DELETE t FROM wf_process_task t
JOIN wf_process_instance i ON i.id = t.processInstanceId
JOIN wf_process_define d ON d.id = i.processDefineId
WHERE d.name IN ('XHZC','XHRH','XHTH','XHPY','XHNS','XHBGLS','XHHJBG','XHZCXD');
DELETE i FROM wf_process_instance i
JOIN wf_process_define d ON d.id = i.processDefineId
WHERE d.name IN ('XHZC','XHRH','XHTH','XHPY','XHNS','XHBGLS','XHHJBG','XHZCXD');
DELETE FROM sys_user_role WHERE NULLIF(TRIM(clubId), '') IS NOT NULL;
DELETE FROM club_pay_record;
DELETE FROM club_user_apply;
DELETE FROM club_user;
DELETE FROM sys_club_evaluate;
DELETE FROM sys_club_examine_register_detailed;
DELETE FROM sys_club_examine_register;
DELETE FROM sys_club_manager;
DELETE FROM sys_club_refresh;
DELETE FROM sys_club_rule;
DELETE FROM sys_club_sponsor;
DELETE FROM sys_club_user_back_history;
DELETE FROM sys_club_user;
DELETE FROM sys_club_files;
DELETE FROM sys_club;
-- v3 社团主数据:字段不对应的值保持为空,不做兜底拼装。
INSERT INTO sys_club(
id, clubName, clubCode, clubType, concatPerson, concatPersonMobile, concatPersonEmail,
introduce, purpose, createTime, foundTime, dismiss, due, files, establishReport,
rulesFile, manageFile, yearPlanFile, userId, QQGroupCode, wechatGroupCode,
replaceReport, createdBy, createdAt, updatedBy, updatedAt, delFlag,
afterRulesFile, schoolReplyFile, state, ruleState, reportState
)
SELECT
s.id, s.name, s.code,
CASE s.type WHEN 'tyjj' THEN '体育竞技' WHEN 'whys' THEN '文化艺术' ELSE NULL END,
s.concatPerson, s.concatPersonMobile, s.concatPersonEmail,
s.stjs, s.stzc, s.create_time, s.foundTime, COALESCE(s.isjs, 0), s.dues_standard,
NULL, NULL, NULL, NULL, NULL, s.userid,
CAST(s.QQGroupCode AS CHAR), CAST(s.wechatGroupCode AS CHAR), NULL,
s.userid,
CASE WHEN STR_TO_DATE(s.create_time, '%Y-%m-%d %H:%i:%s') IS NULL THEN NULL ELSE UNIX_TIMESTAMP(STR_TO_DATE(s.create_time, '%Y-%m-%d %H:%i:%s')) * 1000 END,
s.userid,
CASE WHEN STR_TO_DATE(s.create_time, '%Y-%m-%d %H:%i:%s') IS NULL THEN NULL ELSE UNIX_TIMESTAMP(STR_TO_DATE(s.create_time, '%Y-%m-%d %H:%i:%s')) * 1000 END,
0, NULL, NULL, CAST(s.state AS CHAR), s.ruleState, NULL
FROM union_swufe.sys_club s;
INSERT INTO sys_club_sponsor(id, clubId, sponsorId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT id, clubId, sponsorId, sponsorId, @migration_time, sponsorId, @migration_time, 0
FROM union_swufe.sys_club_sponsor;
-- 正式成员仅迁移 clubId 明确且 status=5 的14条;2条无社团ID和1条待审核记录不强迁。
INSERT INTO club_user(id, clubId, userId, roleCode, clubPosition, email, avatar,
sameTimeJoinOtherClubSituation, awardsExperience,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT s.id, s.clubid, s.userid,
JSON_ARRAY(CASE s.sf
WHEN 1 THEN 'CLUB_PRESIDENT'
WHEN 2 THEN 'CLUB_MEMBER'
WHEN 3 THEN 'CLUB_VICE_PRESIDENT'
WHEN 4 THEN 'CLUB_SECRETARY'
WHEN 5 THEN 'CLUB_VICE_SECRETARY'
END),
s.position, NULL, NULL, NULL, NULL,
s.userid,
CASE WHEN STR_TO_DATE(s.join_time, '%Y-%m-%d %H:%i:%s') IS NULL THEN @migration_time ELSE UNIX_TIMESTAMP(STR_TO_DATE(s.join_time, '%Y-%m-%d %H:%i:%s')) * 1000 END,
s.userid, @migration_time, 0
FROM union_swufe.sys_club_user s
WHERE s.clubid IS NOT NULL AND s.status = 5 AND s.sf IN (1,2,3,4,5);
-- 保留旧兼容表可明确对应的字段,供现有统计和旧查询使用。
INSERT INTO sys_club_user(
id, clubId, userId, joinTime, roleCode, payed, giveMoney, status, exitStatus,
state, changeRoleCode, roleCodeChangeTime, auditList, exitAuditList, isNormal,
changeTime, position, mode, email, avatar, sameTimeJoinOtherClubSituation,
awardsExperience, createdBy, createdAt, updatedBy, updatedAt, delFlag
)
SELECT s.id, s.clubid, s.userid, s.join_time,
CASE s.sf WHEN 1 THEN 'CLUB_PRESIDENT' WHEN 2 THEN 'CLUB_MEMBER'
WHEN 3 THEN 'CLUB_VICE_PRESIDENT' WHEN 4 THEN 'CLUB_SECRETARY'
WHEN 5 THEN 'CLUB_VICE_SECRETARY' END,
s.isjf, s.giveMoney, s.status, NULL, s.state,
CASE s.changeSf WHEN 1 THEN 'CLUB_PRESIDENT' WHEN 2 THEN 'CLUB_MEMBER'
WHEN 3 THEN 'CLUB_VICE_PRESIDENT' WHEN 4 THEN 'CLUB_SECRETARY'
WHEN 5 THEN 'CLUB_VICE_SECRETARY' END,
s.sfChangeTime, s.auditList, NULL, s.isNormal, s.changeTime, s.position,
TRUE, NULL, NULL, NULL, NULL, s.userid,
CASE WHEN STR_TO_DATE(s.join_time, '%Y-%m-%d %H:%i:%s') IS NULL THEN @migration_time ELSE UNIX_TIMESTAMP(STR_TO_DATE(s.join_time, '%Y-%m-%d %H:%i:%s')) * 1000 END,
s.userid, @migration_time, 0
FROM union_swufe.sys_club_user s
WHERE s.clubid IS NOT NULL AND s.status = 5 AND s.sf IN (1,2,3,4,5);
-- 社团角色必须按 v4 角色编码重新取 roleId,禁止复制 v3 角色ID。
INSERT INTO sys_user_role(roleId, userId, clubId)
SELECT r.id, s.userid, s.clubid
FROM union_swufe.sys_club_user s
JOIN sys_role r ON r.code = CASE s.sf
WHEN 1 THEN 'CLUB_PRESIDENT' WHEN 2 THEN 'CLUB_MEMBER'
WHEN 3 THEN 'CLUB_VICE_PRESIDENT' WHEN 4 THEN 'CLUB_SECRETARY'
WHEN 5 THEN 'CLUB_VICE_SECRETARY' END
WHERE s.clubid IS NOT NULL AND s.status = 5 AND s.sf IN (1,2,3,4,5);
-- 旧系统没有 v4 流程表。12个社团均为930且审核ID为空,只创建已完成注册实例,
-- 用 legacyMigration/directPassNote 明确标记迁移事实,不生成虚假的审核任务、审核人和意见。
SET @xhzc_define_id = (SELECT id FROM wf_process_define WHERE name = 'XHZC' AND state = 1 AND delFlag = 0 ORDER BY version DESC, id DESC LIMIT 1);
INSERT INTO wf_process_instance(
parentId, processDefineId, state, parentNodeName, businessNo, operator, expireTime,
variable, createdBy, createdAt, updatedBy, updatedAt, delFlag
)
SELECT NULL, @xhzc_define_id, 20, NULL, s.id, s.userid, NULL,
JSON_OBJECT(
'f_data', JSON_OBJECT('id', s.id, 'clubName', s.name, 'clubCode', s.code,
'clubType', CASE s.type WHEN 'tyjj' THEN '体育竞技' WHEN 'whys' THEN '文化艺术' ELSE NULL END,
'concatPerson', s.concatPerson, 'foundTime', s.foundTime, 'createTime', s.create_time),
'initiator', s.userid,
'initiatorName', COALESCE(u.username, ''),
'initiatorAccount', COALESCE(u.loginname, ''),
'initiatorUnitId', COALESCE(u.unitId, ''),
'initiatorUnitName', COALESCE(unit.name, ''),
'submitType', 0,
'legacyMigration', TRUE,
'legacySource', 'union_swufe',
'legacyState', s.state,
'legacyProcess', '社团注册',
'directPass', TRUE,
'directPassNote', 'v3社团状态为930且审核ID为空,仅迁移为已完成实例,未伪造审核任务和审核意见'
),
s.userid,
CASE WHEN STR_TO_DATE(s.create_time, '%Y-%m-%d %H:%i:%s') IS NULL THEN @migration_time ELSE UNIX_TIMESTAMP(STR_TO_DATE(s.create_time, '%Y-%m-%d %H:%i:%s')) * 1000 END,
s.userid, @migration_time, 0
FROM union_swufe.sys_club s
LEFT JOIN sys_user u ON CONVERT(u.id USING utf8mb4) = CONVERT(s.userid USING utf8mb4) COLLATE utf8mb4_0900_ai_ci
LEFT JOIN sys_unit unit ON unit.id = u.unitId
WHERE s.state = 930;
-- 原 v4 社团ID被经费/文章引用。仅同名可明确匹配的3个社团转换到v3 ID;
-- 其余无同名目标的数据保留业务记录,但将clubId置空,避免形成错误社团关联。
UPDATE outlay_manage_club o
JOIN bak_sys_club_20260813_v3_club oldc ON oldc.id = o.clubId
LEFT JOIN union_swufe.sys_club newc
ON CONVERT(newc.name USING utf8mb4) = CONVERT(oldc.clubName USING utf8mb4) COLLATE utf8mb4_0900_ai_ci
SET o.clubId = newc.id;
UPDATE article a
JOIN bak_sys_club_20260813_v3_club oldc ON oldc.id = a.clubId
LEFT JOIN union_swufe.sys_club newc
ON CONVERT(newc.name USING utf8mb4) = CONVERT(oldc.clubName USING utf8mb4) COLLATE utf8mb4_0900_ai_ci
SET a.clubId = newc.id;
-- 原库中少量clubId本来就无法关联旧社团主表;迁移后统一置空,禁止误连到新社团。
UPDATE outlay_manage_club o
LEFT JOIN sys_club c ON c.id = o.clubId
SET o.clubId = NULL
WHERE o.clubId IS NOT NULL AND c.id IS NULL;
UPDATE article a
LEFT JOIN sys_club c ON c.id = a.clubId
SET a.clubId = NULL
WHERE a.clubId IS NOT NULL AND c.id IS NULL;
DROP TEMPORARY TABLE IF EXISTS tmp_club_final_guard;
CREATE TEMPORARY TABLE tmp_club_final_guard(name VARCHAR(64), actual BIGINT, expected BIGINT, bad INT AS (actual <> expected) STORED) ENGINE=InnoDB;
INSERT INTO tmp_club_final_guard(name, actual, expected) SELECT 'target_club_count', COUNT(*), 12 FROM sys_club;
INSERT INTO tmp_club_final_guard(name, actual, expected) SELECT 'target_member_count', COUNT(*), 14 FROM club_user;
INSERT INTO tmp_club_final_guard(name, actual, expected) SELECT 'target_legacy_member_count', COUNT(*), 14 FROM sys_club_user;
INSERT INTO tmp_club_final_guard(name, actual, expected) SELECT 'target_sponsor_count', COUNT(*), 2 FROM sys_club_sponsor;
INSERT INTO tmp_club_final_guard(name, actual, expected) SELECT 'target_club_role_count', COUNT(*), 14 FROM sys_user_role WHERE NULLIF(TRIM(clubId), '') IS NOT NULL;
INSERT INTO tmp_club_final_guard(name, actual, expected)
SELECT 'target_register_instance_count', COUNT(*), 12
FROM wf_process_instance i JOIN wf_process_define d ON d.id = i.processDefineId
WHERE d.name = 'XHZC' AND i.state = 20;
INSERT INTO tmp_club_final_guard(name, actual, expected)
SELECT 'orphan_member_club', COUNT(*), 0 FROM club_user u LEFT JOIN sys_club c ON c.id = u.clubId WHERE c.id IS NULL;
INSERT INTO tmp_club_final_guard(name, actual, expected)
SELECT 'orphan_role_club', COUNT(*), 0 FROM sys_user_role r LEFT JOIN sys_club c ON c.id = r.clubId WHERE NULLIF(TRIM(r.clubId), '') IS NOT NULL AND c.id IS NULL;
INSERT INTO tmp_club_final_guard(name, actual, expected)
SELECT 'duplicate_member', COUNT(*), 0 FROM (SELECT clubId,userId,COUNT(*) cnt FROM club_user GROUP BY clubId,userId HAVING COUNT(*) > 1) d;
DROP TEMPORARY TABLE IF EXISTS tmp_club_final_guard_fail;
CREATE TEMPORARY TABLE tmp_club_final_guard_fail(id INT NOT NULL) ENGINE=InnoDB;
INSERT INTO tmp_club_final_guard_fail SELECT NULL FROM tmp_club_final_guard WHERE bad = 1 LIMIT 1;
COMMIT;
SELECT * FROM tmp_club_guard ORDER BY name;
SELECT * FROM tmp_club_final_guard ORDER BY name;