Files
railwaysystem/RuoYi-Vue/sql/system/kingbase/006_accommodation_history_constraint.sql
T

69 lines
3.1 KiB
SQL
Raw Normal View History

-- 006_accommodation_history_constraint.sql
-- 目标:移除 train_accommodation 全局唯一约束 uq_accommodation_enroll,
-- 创建部分唯一索引 uq_accommodation_enroll_active (每个 enrollment 最多 1 条有效住宿),
-- 允许学员拥有多条退宿历史记录 (status=2),彻底支持调房与历史留痕。
DO $$
DECLARE
v_dup_count INTEGER;
v_con_def TEXT;
v_idx_def TEXT;
BEGIN
-- 1. Pre-Migration Data Safety Guard
-- 检查是否已存在同一个 enrollment_id 拥有 2 条或以上处于有效状态 (0=预分配, 1=已入住) 的住宿记录
SELECT COUNT(*) INTO v_dup_count
FROM (
SELECT enrollment_id
FROM train_accommodation
WHERE accommodation_status IN (0, 1)
GROUP BY enrollment_id
HAVING COUNT(*) > 1
) t;
IF v_dup_count > 0 THEN
RAISE EXCEPTION 'Pre-migration check failed: found % enrollment(s) with multiple active accommodations (status IN (0,1)). Manual resolution required before applying migration 006.', v_dup_count;
END IF;
-- 2. Existing Constraint Guard (Idempotent Drop)
-- 检查约束 uq_accommodation_enroll 是否存在且符合预期
SELECT pg_get_constraintdef(c.oid) INTO v_con_def
FROM pg_constraint c
JOIN pg_class t ON c.conrelid = t.oid
WHERE t.relname = 'train_accommodation'
AND c.conname = 'uq_accommodation_enroll';
IF v_con_def IS NOT NULL THEN
-- 验证旧约束是否为 UNIQUE (enrollment_id)
IF v_con_def ILIKE 'UNIQUE (enrollment_id)%' THEN
RAISE NOTICE 'Dropping legacy global unique constraint: uq_accommodation_enroll';
ALTER TABLE train_accommodation DROP CONSTRAINT uq_accommodation_enroll;
ELSE
RAISE EXCEPTION 'Constraint collision: constraint uq_accommodation_enroll exists but definition is unexpected: %', v_con_def;
END IF;
ELSE
RAISE NOTICE 'Constraint uq_accommodation_enroll does not exist, skipping drop.';
END IF;
-- 3. New Index Collision Guard & Creation
-- 检查部分唯一索引 uq_accommodation_enroll_active
SELECT pg_get_indexdef(i.indexrelid) INTO v_idx_def
FROM pg_index i
JOIN pg_class c ON i.indexrelid = c.oid
JOIN pg_class t ON i.indrelid = t.oid
WHERE t.relname = 'train_accommodation'
AND c.relname = 'uq_accommodation_enroll_active';
IF v_idx_def IS NOT NULL THEN
-- 验证已有索引是否为预期的部分唯一索引
IF v_idx_def ILIKE '%UNIQUE INDEX uq_accommodation_enroll_active ON %train_accommodation%enrollment_id%WHERE%accommodation_status%' THEN
RAISE NOTICE 'Partial unique index uq_accommodation_enroll_active already exists with expected definition, skipping creation.';
ELSE
RAISE EXCEPTION 'Index collision: index uq_accommodation_enroll_active exists but definition differs: %', v_idx_def;
END IF;
ELSE
RAISE NOTICE 'Creating partial unique index: uq_accommodation_enroll_active';
CREATE UNIQUE INDEX uq_accommodation_enroll_active
ON train_accommodation (enrollment_id)
WHERE accommodation_status IN (0, 1);
END IF;
END $$;