-- Starbook 典藏/活动藏品体系重构 - 数据库迁移 -- 创建时间: 2026-04-17 -- 状态: 新建(非破坏性变更) -- ============================================= -- 1. 典藏藏品表 collection_assets -- ============================================= CREATE TABLE IF NOT EXISTS collection_assets ( id BIGSERIAL PRIMARY KEY, asset_id BIGINT UNIQUE NOT NULL, owner_uid BIGINT NOT NULL, star_id BIGINT NOT NULL, name VARCHAR(100) NOT NULL, cover_url VARCHAR(500) NOT NULL, category VARCHAR(50) NOT NULL, like_count INT NOT NULL DEFAULT 0, status SMALLINT NOT NULL DEFAULT 0, metadata JSONB, created_at BIGINT NOT NULL, updated_at BIGINT NOT NULL, CONSTRAINT uk_collection_owner_star_name UNIQUE (owner_uid, star_id, name) ); CREATE INDEX IF NOT EXISTS idx_collection_owner_star ON collection_assets (owner_uid, star_id); CREATE INDEX IF NOT EXISTS idx_collection_category ON collection_assets (category); CREATE INDEX IF NOT EXISTS idx_collection_asset_id ON collection_assets (asset_id); -- ============================================= -- 2. 活动藏品表 activity_assets -- ============================================= CREATE TABLE IF NOT EXISTS activity_assets ( id BIGSERIAL PRIMARY KEY, asset_id BIGINT UNIQUE NOT NULL, owner_uid BIGINT NOT NULL, star_id BIGINT NOT NULL, activity_id BIGINT NOT NULL, activity_type VARCHAR(50) NOT NULL, name VARCHAR(100) NOT NULL, cover_url VARCHAR(500) NOT NULL, like_count INT NOT NULL DEFAULT 0, status SMALLINT NOT NULL DEFAULT 0, metadata JSONB, created_at BIGINT NOT NULL, updated_at BIGINT NOT NULL, CONSTRAINT uk_activity_owner_activity_name UNIQUE (owner_uid, activity_id, name) ); CREATE INDEX IF NOT EXISTS idx_activity_owner ON activity_assets (owner_uid, activity_id); CREATE INDEX IF NOT EXISTS idx_activity_star ON activity_assets (star_id, activity_id); CREATE INDEX IF NOT EXISTS idx_activity_type ON activity_assets (activity_type); CREATE INDEX IF NOT EXISTS idx_activity_asset_id ON activity_assets (asset_id); -- ============================================= -- 3. 统一索引表 asset_registry -- ============================================= CREATE TABLE IF NOT EXISTS asset_registry ( id BIGSERIAL PRIMARY KEY, asset_id BIGINT NOT NULL, asset_type VARCHAR(20) NOT NULL, owner_uid BIGINT NOT NULL, star_id BIGINT NOT NULL, -- 普通藏品专属字段(其他类型时为 NULL) grade SMALLINT, -- 典藏专属字段(其他类型时为 NULL) collection_category VARCHAR(50), -- 活动专属字段(其他类型时为 NULL) activity_id BIGINT, activity_type VARCHAR(50), -- 公共字段 status SMALLINT NOT NULL DEFAULT 0, like_count INT NOT NULL DEFAULT 0, created_at BIGINT NOT NULL, updated_at BIGINT NOT NULL, CONSTRAINT uk_registry_asset_type_id UNIQUE (asset_type, asset_id), CONSTRAINT uk_registry_owner_star_type_asset UNIQUE (owner_uid, star_id, asset_type, asset_id) ); CREATE INDEX IF NOT EXISTS idx_registry_owner_star ON asset_registry (owner_uid, star_id); CREATE INDEX IF NOT EXISTS idx_registry_type_star ON asset_registry (asset_type, star_id); CREATE INDEX IF NOT EXISTS idx_registry_star_grade ON asset_registry (star_id, grade) WHERE asset_type = 'regular'; CREATE INDEX IF NOT EXISTS idx_registry_star_activity ON asset_registry (star_id, activity_id) WHERE asset_type = 'activity'; -- ============================================= -- 注释说明 -- ============================================= COMMENT ON TABLE collection_assets IS '典藏藏品表'; COMMENT ON TABLE activity_assets IS '活动藏品表'; COMMENT ON TABLE asset_registry IS '资产统一索引表'; COMMENT ON COLUMN collection_assets.category IS '典藏子分类(如 limited, classic)'; COMMENT ON COLUMN activity_assets.activity_type IS '活动类型(如 birthday, anniversary, concert)'; COMMENT ON COLUMN asset_registry.asset_type IS '资产类型:regular(普通) | collection(典藏) | activity(活动)'; COMMENT ON COLUMN asset_registry.grade IS '普通藏品等级:1/2/3...(仅 regular 类型有效)'; -- ============================================= -- 4. 修改 assets 表:将 rarity 改名为 grade -- ============================================= -- 注意:如果 assets.rarity 字段不存在(新建数据库),则跳过此步 DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'assets' AND column_name = 'rarity') THEN ALTER TABLE assets RENAME COLUMN rarity TO grade; COMMENT ON COLUMN assets.grade IS '星册等级:1/2/3...(铸爱流程创建时默认值为1)'; END IF; END $$;