Files
familyactivity-service/src/main/resources/sql/archive/notice_data_backfill.sql
T
wanghu d8d11804db sql
Signed-off-by: wanghu <wanghu@yuanhai.com>
2026-09-20 09:34:54 +08:00

160 lines
5.8 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- ============================================================
-- 存量数据回填脚本
-- 1. notice.sch_id:按发布人所属学校回填(从 sys_user_role_rel 取 main=1 的 sch_id)
-- 2. notice_receiver:从 notice.receive_list JSON 字符串展开为关联表行
--
-- 幂等设计:可重复执行,已存在的数据不会重复插入
-- 执行方式:由 DBA 手动在对应环境执行,AI 不代跑
-- MySQL 5.7+ 兼容
-- ============================================================
-- ============================================================
-- Part 1:回填 notice.sch_id
-- ============================================================
-- 方式一:如果 base_user / sys_user 表有 sch_id 字段,直接关联回填
-- 注意:需根据实际平台库表结构调整关联条件
UPDATE `notice` n
INNER JOIN (
SELECT DISTINCT u.login_name, u.sch_id
FROM base_user u
WHERE u.sch_id IS NOT NULL
) t ON n.publisher_account = t.login_name
SET n.sch_id = t.sch_id
WHERE n.sch_id IS NULL
AND n.publisher_account IS NOT NULL
AND n.publisher_account != '';
-- 方式二(备用):如果用户学校关系在 sys_user_role_rel 表
-- 取每个用户的主身份学校(is_main=1),回填 sch_id
-- 取消注释后执行(视实际库表结构选用)
--
-- UPDATE `notice` n
-- INNER JOIN (
-- SELECT r.account, r.sch_id
-- FROM sys_user_role_rel r
-- WHERE r.is_main = 1
-- AND r.sch_id IS NOT NULL
-- ) t ON n.publisher_account = t.account
-- SET n.sch_id = t.sch_id
-- WHERE n.sch_id IS NULL
-- AND n.publisher_account IS NOT NULL
-- AND n.publisher_account != '';
-- ============================================================
-- Part 2:从 notice.receive_list 展开到 notice_receiver 关联表
-- ============================================================
-- 说明:
-- - notice.receive_list 存储格式有两种:
-- 1) "ALL"(全员通知)—— 不写明细行,跳过
-- 2) JSON 数组 ["account1","account2",...] 或逗号分隔串
-- - 本脚本使用 MySQL JSON 函数解析(MySQL 5.7+ 支持 JSON_EXTRACT)
-- - 对于非标准 JSON 格式(逗号分隔串),使用循环逐条插入
-- - 幂等:每次插入前先删除该通知的旧接收人记录
-- 注意:MySQL 5.7 的 JSON_TABLE 不可用,这里用存储过程逐条解析
-- 如果 receive_list 是标准 JSON 数组格式,可以直接用 JSON_EXTRACT
DELIMITER $$
-- 存储过程:展开单个通知的接收人列表
DROP PROCEDURE IF EXISTS `expand_notice_receivers`$$
CREATE PROCEDURE `expand_notice_receivers`()
BEGIN
DECLARE v_done INT DEFAULT 0;
DECLARE v_notice_id INT;
DECLARE v_receive_list TEXT;
DECLARE cur CURSOR FOR
SELECT id, receive_list
FROM notice
WHERE receive_list IS NOT NULL
AND TRIM(receive_list) != ''
AND UPPER(TRIM(receive_list)) != 'ALL'
AND NOT EXISTS (
SELECT 1 FROM notice_receiver WHERE notice_id = notice.id LIMIT 1
);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1;
OPEN cur;
read_loop: LOOP
FETCH cur INTO v_notice_id, v_receive_list;
IF v_done = 1 THEN
LEAVE read_loop;
END IF;
-- 清理旧数据(幂等)
DELETE FROM notice_receiver WHERE notice_id = v_notice_id;
-- 尝试 JSON 数组解析
-- receive_list 格式: ["account1","account2"] 或 account1,account2
SET v_receive_list = TRIM(v_receive_list);
-- 去除首尾方括号(如有)
IF LEFT(v_receive_list, 1) = '[' AND RIGHT(v_receive_list, 1) = ']' THEN
SET v_receive_list = SUBSTRING(v_receive_list, 2, CHAR_LENGTH(v_receive_list) - 2);
END IF;
-- 替换引号为空,按逗号分隔
SET v_receive_list = REPLACE(REPLACE(v_receive_list, '"', ''), '''', '');
-- 逐条插入
-- 简单实现:用 FIND_IN_SET 不适用于变量,改用临时表
BEGIN
DECLARE v_pos INT DEFAULT 1;
DECLARE v_account VARCHAR(64);
DECLARE v_remaining TEXT;
SET v_remaining = v_receive_list;
WHILE v_remaining IS NOT NULL AND TRIM(v_remaining) != '' DO
IF LOCATE(',', v_remaining) > 0 THEN
SET v_account = TRIM(SUBSTRING_INDEX(v_remaining, ',', 1));
SET v_remaining = SUBSTRING(v_remaining, LOCATE(',', v_remaining) + 1);
ELSE
SET v_account = TRIM(v_remaining);
SET v_remaining = NULL;
END IF;
IF v_account != '' AND v_account IS NOT NULL THEN
INSERT INTO notice_receiver (notice_id, account, receive_type, create_time)
VALUES (v_notice_id, v_account, 1, NOW());
END IF;
END WHILE;
END;
END LOOP;
CLOSE cur;
END$$
DELIMITER ;
-- 执行存储过程
CALL expand_notice_receivers();
-- 清理临时存储过程
DROP PROCEDURE IF EXISTS `expand_notice_receivers`;
-- ============================================================
-- 回填结果验证查询(执行后手动检查)
-- ============================================================
-- 检查1:sch_id 回填覆盖率
-- SELECT
-- COUNT(*) AS total,
-- SUM(CASE WHEN sch_id IS NOT NULL THEN 1 ELSE 0 END) AS sch_id_filled,
-- SUM(CASE WHEN sch_id IS NULL THEN 1 ELSE 0 END) AS sch_id_null
-- FROM notice;
-- 检查2:notice_receiver 展开行数
-- SELECT COUNT(*) FROM notice_receiver;
-- 检查3:未展开的通知(receive_list 非空非 ALL 但 receiver 表无记录)
-- SELECT n.id, n.receive_list
-- FROM notice n
-- LEFT JOIN notice_receiver r ON r.notice_id = n.id
-- WHERE n.receive_list IS NOT NULL
-- AND TRIM(n.receive_list) != ''
-- AND UPPER(TRIM(n.receive_list)) != 'ALL'
-- AND r.id IS NULL;