63 lines
2.9 KiB
SQL
63 lines
2.9 KiB
SQL
-- 2026-10-16-01-brands-renumber-imported-ids.sql
|
||
--
|
||
-- 背景:2026-10-16 从 app_brands(MySQL dump)导入的 23218 个品牌带的是**源系统的显式 id**
|
||
-- (3097..26472)。而 brands.id 本身是 IDENTITY 列(GENERATED ... AS IDENTITY,序列
|
||
-- brands_id_seq),导入后序列仍停在 30 —— 新增品牌会从 31 开始编号,一旦涨到 3097
|
||
-- 就会与这批导入行**撞主键**。本迁移把那批行重排进真正的自增空间,并把序列对齐过去。
|
||
--
|
||
-- 安全性(迁移前已核对):全库没有任何行引用这些 id ——
|
||
-- * brand_runways.brand_id 最大只有 7(115 场走秀全部落在 19 个种子品牌内);
|
||
-- * favorites / histories 存的是内容(走秀/街拍)快照,不存品牌 id。
|
||
-- 19 个种子品牌(id ≤ 19)完全不动。
|
||
--
|
||
-- 三步:① 整批挪到负区间(避开主键中途相撞)② 按原 id 升序落回 20 起的连续区间
|
||
-- ③ 把 IDENTITY 序列对齐到新的最大值(下一次 nextval 即 max+1)。
|
||
--
|
||
-- ⚠️ 第 ② 步的 JOIN 必须用「当前的负数 id 本身」去匹配,**不能**拿子查询里的 -id(正数)
|
||
-- 去比 b.id(负数)—— 那样一行都匹配不上,会留下满表负数 id 的半途状态(本文件初版就踩了)。
|
||
--
|
||
-- 幂等:仅当「种子(≤19) 与导入批次(≥3097) 之间存在空洞(20..3096 全空)」时才重排;
|
||
-- 重排后 20..3096 已被占满,手动重跑会直接跳过。dbtool migrate 另按 schema_migrations 记账。
|
||
|
||
DO $$
|
||
DECLARE
|
||
v_before_max integer;
|
||
v_moved integer;
|
||
v_after_max integer;
|
||
BEGIN
|
||
IF EXISTS (SELECT 1 FROM brands WHERE id BETWEEN 20 AND 3096) THEN
|
||
RAISE NOTICE '[brands-renumber] 20..3096 非空,说明已重排过,跳过';
|
||
RETURN;
|
||
END IF;
|
||
|
||
-- 待处理的行:原始状态的 id >= 3097,或上一次中断留下的负数行。
|
||
IF NOT EXISTS (SELECT 1 FROM brands WHERE id < 0 OR id >= 3097) THEN
|
||
RAISE NOTICE '[brands-renumber] 没有待重排的行,跳过';
|
||
RETURN;
|
||
END IF;
|
||
|
||
SELECT max(id) INTO v_before_max FROM brands;
|
||
|
||
-- 1) 原始状态:整批挪到负区间(若已是负数则天然不匹配,空跑)。
|
||
UPDATE brands SET id = -id WHERE id >= 3097;
|
||
GET DIAGNOSTICS v_moved = ROW_COUNT;
|
||
|
||
-- 2) 按原 id 升序落回「紧接 19 个种子之后」的连续区间(排序固定,结果可复现)。
|
||
UPDATE brands b
|
||
SET id = m.new_id
|
||
FROM (
|
||
SELECT id AS neg_id,
|
||
(row_number() OVER (ORDER BY -id))::integer + 19 AS new_id
|
||
FROM brands
|
||
WHERE id < 0
|
||
) m
|
||
WHERE b.id = m.neg_id;
|
||
|
||
-- 3) 把 IDENTITY 序列对齐到新的最大值。
|
||
SELECT max(id) INTO v_after_max FROM brands;
|
||
PERFORM setval(pg_get_serial_sequence('brands', 'id'), v_after_max);
|
||
|
||
RAISE NOTICE '[brands-renumber] 完成:负区间挪动 % 行,id 最大值 % -> %,序列下次给出 %',
|
||
v_moved, v_before_max, v_after_max, v_after_max + 1;
|
||
END $$;
|