分裂iccid长度
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m47s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m47s
This commit is contained in:
7
migrations/000131_add_iccid_dual_column.down.sql
Normal file
7
migrations/000131_add_iccid_dual_column.down.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
DROP INDEX IF EXISTS idx_personal_customer_iccid_19;
|
||||
ALTER TABLE tb_personal_customer_iccid DROP COLUMN IF EXISTS iccid_19;
|
||||
|
||||
DROP INDEX IF EXISTS idx_iot_card_iccid_20;
|
||||
DROP INDEX IF EXISTS idx_iot_card_iccid_19;
|
||||
ALTER TABLE tb_iot_card DROP COLUMN IF EXISTS iccid_20;
|
||||
ALTER TABLE tb_iot_card DROP COLUMN IF EXISTS iccid_19;
|
||||
97
migrations/000131_add_iccid_dual_column.up.sql
Normal file
97
migrations/000131_add_iccid_dual_column.up.sql
Normal file
@@ -0,0 +1,97 @@
|
||||
-- 目的:支持上游 IoT 平台传入 19/20 位 ICCID 均能精确命中卡记录
|
||||
-- 背景:部分运营商 19 位为唯一标识,部分运营商需要完整 20 位才能唯一标识一张卡
|
||||
-- 策略:双列存储 + 按上游传入长度路由查询,Miss 时记录 Warn 日志不降级
|
||||
|
||||
-- 注意:golang-migrate 默认在事务中运行,CREATE INDEX CONCURRENTLY 不能在事务中执行
|
||||
-- 因此使用 CREATE INDEX IF NOT EXISTS(非 CONCURRENTLY)
|
||||
-- 生产环境若需零停机建索引,可手动执行 CONCURRENTLY 版本
|
||||
|
||||
-- ==========================================================================
|
||||
-- 1. tb_iot_card 新增双列
|
||||
-- ==========================================================================
|
||||
|
||||
ALTER TABLE tb_iot_card
|
||||
ADD COLUMN IF NOT EXISTS iccid_19 varchar(19),
|
||||
ADD COLUMN IF NOT EXISTS iccid_20 varchar(20);
|
||||
|
||||
COMMENT ON COLUMN tb_iot_card.iccid_19 IS 'ICCID前19位(所有卡必填,用于19位运营商精确查询)';
|
||||
COMMENT ON COLUMN tb_iot_card.iccid_20 IS '完整20位ICCID(仅20位运营商卡有值,19位卡为NULL)';
|
||||
|
||||
-- ==========================================================================
|
||||
-- 1.1a 冲突检测(执行后人工确认均为 0 行,否则停止迁移人工处理)
|
||||
-- 检测 19 位前缀重复:若 19 位前缀不唯一,回填后 iccid_19 无法作为唯一索引列
|
||||
-- ==========================================================================
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
conflict_count INTEGER;
|
||||
abnormal_count INTEGER;
|
||||
BEGIN
|
||||
-- 检测 19 位前缀重复
|
||||
SELECT COUNT(*) INTO conflict_count
|
||||
FROM (
|
||||
SELECT LEFT(iccid, 19)
|
||||
FROM tb_iot_card
|
||||
WHERE deleted_at IS NULL
|
||||
GROUP BY LEFT(iccid, 19)
|
||||
HAVING COUNT(*) > 1
|
||||
) t;
|
||||
|
||||
IF conflict_count > 0 THEN
|
||||
RAISE EXCEPTION '冲突检测失败:发现 % 组 19 位前缀重复的 ICCID,请人工处理后再执行迁移', conflict_count;
|
||||
END IF;
|
||||
|
||||
-- 检测异常长度 ICCID(长度既非 19 也非 20 的记录)
|
||||
SELECT COUNT(*) INTO abnormal_count
|
||||
FROM tb_iot_card
|
||||
WHERE deleted_at IS NULL
|
||||
AND LENGTH(iccid) NOT IN (19, 20);
|
||||
|
||||
IF abnormal_count > 0 THEN
|
||||
RAISE WARNING '警告:发现 % 条异常长度 ICCID 记录(长度非19也非20),回填后这些卡将无法通过新查询路径命中', abnormal_count;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- ==========================================================================
|
||||
-- 1.2 回填存量数据
|
||||
-- iccid_19 = LEFT(iccid, 19)(所有卡)
|
||||
-- iccid_20 = iccid(仅当 LENGTH(iccid)=20,否则 NULL)
|
||||
-- ==========================================================================
|
||||
|
||||
UPDATE tb_iot_card
|
||||
SET iccid_19 = LEFT(iccid, 19),
|
||||
iccid_20 = CASE WHEN LENGTH(iccid) = 20 THEN iccid ELSE NULL END;
|
||||
|
||||
-- ==========================================================================
|
||||
-- 1.3 为 iccid_19 创建 Partial Index(过滤软删除记录)
|
||||
-- ==========================================================================
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_iot_card_iccid_19
|
||||
ON tb_iot_card (iccid_19)
|
||||
WHERE deleted_at IS NULL;
|
||||
|
||||
-- ==========================================================================
|
||||
-- 1.4 为 iccid_20 创建 Partial Index(过滤软删除和 NULL 记录)
|
||||
-- ==========================================================================
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_iot_card_iccid_20
|
||||
ON tb_iot_card (iccid_20)
|
||||
WHERE deleted_at IS NULL AND iccid_20 IS NOT NULL;
|
||||
|
||||
-- ==========================================================================
|
||||
-- 1.5 tb_personal_customer_iccid 新增 iccid_19 列
|
||||
-- ==========================================================================
|
||||
|
||||
ALTER TABLE tb_personal_customer_iccid
|
||||
ADD COLUMN IF NOT EXISTS iccid_19 varchar(19);
|
||||
|
||||
COMMENT ON COLUMN tb_personal_customer_iccid.iccid_19 IS 'ICCID前19位(用于19位运营商精确查询)';
|
||||
|
||||
-- 回填存量数据
|
||||
UPDATE tb_personal_customer_iccid
|
||||
SET iccid_19 = LEFT(iccid, 19);
|
||||
|
||||
-- 创建对应 Partial Index
|
||||
CREATE INDEX IF NOT EXISTS idx_personal_customer_iccid_19
|
||||
ON tb_personal_customer_iccid (iccid_19)
|
||||
WHERE deleted_at IS NULL;
|
||||
Reference in New Issue
Block a user