-- 044 数字主键重构:每张业务表 id bigint GENERATED ALWAYS AS IDENTITY 主键, -- 文本业务标识降级 UNIQUE 并按语义改名;FK 全部重指 bigint id; -- 应用层对外契约不变(API/JSON 仍用文本标识),seed 改由 bigint id + 1000 派生。 -- 依据:docs/plans/2026-09-29-schema-consolidation-and-numeric-id.md 第 3 节。 -- ============ 1) 被引用表:加 bigint 代理主键列(PG 17 IDENTITY 自动回填存量行;rename 在第 4 节)============ ALTER TABLE social_account ADD COLUMN surrogate_id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE network_exit ADD COLUMN surrogate_id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE gateway ADD COLUMN surrogate_id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE browser_env ADD COLUMN surrogate_id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE creator_competitor ADD COLUMN surrogate_id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE creator_work ADD COLUMN surrogate_id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE creator_comment ADD COLUMN surrogate_id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE creator_competitor_share_job ADD COLUMN surrogate_id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE creator_lead_rule ADD COLUMN surrogate_id bigint GENERATED ALWAYS AS IDENTITY; -- ============ 2) 引用表:加 bigint FK 列并按文本标识回填 ============ ALTER TABLE browser_env ADD COLUMN gateway_row_id bigint, ADD COLUMN account_row_id bigint, ADD COLUMN exit_row_id bigint; UPDATE browser_env b SET gateway_row_id = g.surrogate_id FROM gateway g WHERE g.name = b.gateway_name; UPDATE browser_env b SET account_row_id = s.surrogate_id FROM social_account s WHERE s.id::text = b.account_id; UPDATE browser_env b SET exit_row_id = n.surrogate_id FROM network_exit n WHERE n.id::text = b.network_exit_id; ALTER TABLE audit_event ADD COLUMN account_row_id bigint, ADD COLUMN browser_env_row_id bigint, ADD COLUMN exit_row_id bigint; -- audit_event 是 append-only(触发器拦截 UPDATE),回填期间临时摘除。 DROP TRIGGER IF EXISTS audit_event_append_only ON audit_event; UPDATE audit_event a SET account_row_id = s.surrogate_id FROM social_account s WHERE s.id::text = a.account_id; UPDATE audit_event a SET browser_env_row_id = b.surrogate_id FROM browser_env b WHERE b.alias = a.browser_env_alias; UPDATE audit_event a SET exit_row_id = n.surrogate_id FROM network_exit n WHERE n.id::text = a.network_exit_id; ALTER TABLE creator_account_profile ADD COLUMN account_row_id bigint; UPDATE creator_account_profile p SET account_row_id = s.surrogate_id FROM social_account s WHERE s.id::text = p.account_id; ALTER TABLE creator_account_password ADD COLUMN account_row_id bigint; UPDATE creator_account_password p SET account_row_id = s.surrogate_id FROM social_account s WHERE s.id::text = p.account_id; ALTER TABLE creator_account_metric ADD COLUMN account_row_id bigint; UPDATE creator_account_metric m SET account_row_id = s.surrogate_id FROM social_account s WHERE s.id::text = m.account_id; ALTER TABLE creator_competitor_share_job ADD COLUMN competitor_row_id bigint; UPDATE creator_competitor_share_job j SET competitor_row_id = c.surrogate_id FROM creator_competitor c WHERE c.id::text = j.competitor_id; ALTER TABLE creator_work_metric ADD COLUMN work_row_id bigint; UPDATE creator_work_metric m SET work_row_id = w.surrogate_id FROM creator_work w WHERE w.id::text = m.work_id; ALTER TABLE creator_comment ADD COLUMN work_row_id bigint; UPDATE creator_comment c SET work_row_id = w.surrogate_id FROM creator_work w WHERE w.id::text = c.work_id; ALTER TABLE creator_comment_rule_result ADD COLUMN comment_row_id bigint, ADD COLUMN rule_row_id bigint; UPDATE creator_comment_rule_result r SET comment_row_id = c.surrogate_id FROM creator_comment c WHERE c.id::text = r.comment_id; UPDATE creator_comment_rule_result r SET rule_row_id = l.surrogate_id FROM creator_lead_rule l WHERE l.id::text = r.rule_id; ALTER TABLE creator_work_cover ADD COLUMN work_row_id bigint; UPDATE creator_work_cover c SET work_row_id = w.surrogate_id FROM creator_work w WHERE w.id::text = c.work_id; -- ============ 3) 删除全部旧文本 FK(解除对旧文本主键的依赖)============ ALTER TABLE browser_env DROP CONSTRAINT IF EXISTS browser_env_gateway_name_fkey, DROP CONSTRAINT IF EXISTS browser_env_account_id_fkey, DROP CONSTRAINT IF EXISTS browser_env_network_exit_id_fkey; ALTER TABLE audit_event DROP CONSTRAINT IF EXISTS audit_event_account_id_fkey, DROP CONSTRAINT IF EXISTS audit_event_browser_env_alias_fkey, DROP CONSTRAINT IF EXISTS audit_event_network_exit_id_fkey; ALTER TABLE creator_account_profile DROP CONSTRAINT IF EXISTS creator_account_profile_account_id_fkey; ALTER TABLE creator_account_password DROP CONSTRAINT IF EXISTS creator_account_password_account_id_fkey; ALTER TABLE creator_account_metric DROP CONSTRAINT IF EXISTS creator_account_metric_account_id_fkey; ALTER TABLE creator_competitor_share_job DROP CONSTRAINT IF EXISTS creator_competitor_share_job_competitor_id_fkey; ALTER TABLE creator_work_metric DROP CONSTRAINT IF EXISTS creator_work_metric_work_id_fkey; ALTER TABLE creator_comment DROP CONSTRAINT IF EXISTS creator_comment_work_id_fkey; ALTER TABLE creator_comment_rule_result DROP CONSTRAINT IF EXISTS creator_comment_rule_result_comment_id_fkey, DROP CONSTRAINT IF EXISTS creator_comment_rule_result_rule_id_fkey; ALTER TABLE creator_work_cover DROP CONSTRAINT IF EXISTS creator_work_cover_work_id_fkey; -- ============ 4) 文本列名为 id 的表:先降级改名,再加 bigint 主键(PG 17 IDENTITY 自动回填存量行)============ ALTER TABLE social_account DROP CONSTRAINT social_account_pkey; ALTER TABLE social_account RENAME COLUMN id TO account_id; ALTER TABLE social_account RENAME COLUMN surrogate_id TO id; ALTER TABLE social_account ADD PRIMARY KEY (id); ALTER TABLE social_account ADD CONSTRAINT social_account_account_id_unique UNIQUE (account_id); ALTER TABLE network_exit DROP CONSTRAINT network_exit_pkey; ALTER TABLE network_exit RENAME COLUMN id TO exit_id; ALTER TABLE network_exit RENAME COLUMN surrogate_id TO id; ALTER TABLE network_exit ADD PRIMARY KEY (id); ALTER TABLE network_exit ADD CONSTRAINT network_exit_exit_id_unique UNIQUE (exit_id); ALTER TABLE creator_competitor DROP CONSTRAINT creator_competitor_pkey; ALTER TABLE creator_competitor RENAME COLUMN id TO competitor_id; ALTER TABLE creator_competitor RENAME COLUMN surrogate_id TO id; ALTER TABLE creator_competitor ADD PRIMARY KEY (id); ALTER TABLE creator_competitor ADD CONSTRAINT creator_competitor_competitor_id_unique UNIQUE (competitor_id); ALTER TABLE creator_work DROP CONSTRAINT creator_work_pkey; ALTER TABLE creator_work RENAME COLUMN id TO work_id; ALTER TABLE creator_work RENAME COLUMN surrogate_id TO id; ALTER TABLE creator_work ADD PRIMARY KEY (id); ALTER TABLE creator_work ADD CONSTRAINT creator_work_work_id_unique UNIQUE (work_id); ALTER TABLE creator_comment DROP CONSTRAINT creator_comment_pkey; ALTER TABLE creator_comment RENAME COLUMN id TO comment_id; ALTER TABLE creator_comment RENAME COLUMN surrogate_id TO id; ALTER TABLE creator_comment ADD PRIMARY KEY (id); ALTER TABLE creator_comment ADD CONSTRAINT creator_comment_comment_id_unique UNIQUE (comment_id); ALTER TABLE creator_competitor_share_job DROP CONSTRAINT creator_competitor_share_job_pkey; ALTER TABLE creator_competitor_share_job RENAME COLUMN id TO job_id; ALTER TABLE creator_competitor_share_job RENAME COLUMN surrogate_id TO id; ALTER TABLE creator_competitor_share_job ADD PRIMARY KEY (id); ALTER TABLE creator_competitor_share_job ADD CONSTRAINT creator_competitor_share_job_job_id_unique UNIQUE (job_id); ALTER TABLE creator_lead_rule DROP CONSTRAINT creator_lead_rule_pkey; ALTER TABLE creator_lead_rule RENAME COLUMN id TO rule_id; ALTER TABLE creator_lead_rule RENAME COLUMN surrogate_id TO id; ALTER TABLE creator_lead_rule ADD PRIMARY KEY (id); ALTER TABLE creator_lead_rule ADD CONSTRAINT creator_lead_rule_rule_id_unique UNIQUE (rule_id); -- ============ 5) 文本主键为语义列的表:加 bigint 主键,文本列降级 UNIQUE ============ ALTER TABLE gateway DROP CONSTRAINT gateway_pkey; ALTER TABLE gateway RENAME COLUMN surrogate_id TO id; ALTER TABLE gateway ADD PRIMARY KEY (id); ALTER TABLE gateway ADD CONSTRAINT gateway_name_unique UNIQUE (name); ALTER TABLE browser_env DROP CONSTRAINT browser_env_pkey; ALTER TABLE browser_env RENAME COLUMN surrogate_id TO id; ALTER TABLE browser_env ADD PRIMARY KEY (id); -- alias 原本就是 NOT NULL,降级为 UNIQUE(账号即环境下 alias = 账号文本 ID)。 ALTER TABLE browser_env ADD CONSTRAINT browser_env_alias_unique UNIQUE (alias); -- ============ 6) 引用表换列:删文本 FK 列(连带旧 FK/PK/UNIQUE/索引),新列更名 + 补约束 ============ ALTER TABLE browser_env DROP COLUMN gateway_name, DROP COLUMN account_id, DROP COLUMN network_exit_id; ALTER TABLE browser_env RENAME COLUMN gateway_row_id TO gateway_id; ALTER TABLE browser_env RENAME COLUMN account_row_id TO account_id; ALTER TABLE browser_env RENAME COLUMN exit_row_id TO exit_id; ALTER TABLE browser_env ALTER COLUMN gateway_id SET NOT NULL, ALTER COLUMN account_id SET NOT NULL, ADD CONSTRAINT browser_env_account_id_unique UNIQUE (account_id), ADD CONSTRAINT browser_env_account_id_fkey FOREIGN KEY (account_id) REFERENCES social_account(id) ON DELETE CASCADE, ADD CONSTRAINT browser_env_gateway_id_fkey FOREIGN KEY (gateway_id) REFERENCES gateway(id), ADD CONSTRAINT browser_env_exit_id_fkey FOREIGN KEY (exit_id) REFERENCES network_exit(id); ALTER TABLE audit_event DROP COLUMN account_id, DROP COLUMN browser_env_alias, DROP COLUMN network_exit_id; ALTER TABLE audit_event RENAME COLUMN account_row_id TO account_id; ALTER TABLE audit_event RENAME COLUMN browser_env_row_id TO browser_env_id; ALTER TABLE audit_event RENAME COLUMN exit_row_id TO exit_id; ALTER TABLE audit_event ADD CONSTRAINT audit_event_account_id_fkey FOREIGN KEY (account_id) REFERENCES social_account(id), ADD CONSTRAINT audit_event_browser_env_id_fkey FOREIGN KEY (browser_env_id) REFERENCES browser_env(id), ADD CONSTRAINT audit_event_exit_id_fkey FOREIGN KEY (exit_id) REFERENCES network_exit(id); CREATE TRIGGER audit_event_append_only BEFORE UPDATE OR DELETE ON audit_event FOR EACH ROW EXECUTE FUNCTION reject_audit_event_mutation(); -- social_account.profile_id 是 creator_account_profile 的悬空文本镜像(1:1 已由对方 account_id 表达),删除。 ALTER TABLE social_account DROP COLUMN profile_id; ALTER TABLE creator_account_profile DROP CONSTRAINT creator_account_profile_pkey, DROP COLUMN account_id; ALTER TABLE creator_account_profile RENAME COLUMN account_row_id TO account_id; ALTER TABLE creator_account_profile ALTER COLUMN account_id SET NOT NULL, ADD PRIMARY KEY (account_id), ADD CONSTRAINT creator_account_profile_account_id_fkey FOREIGN KEY (account_id) REFERENCES social_account(id) ON DELETE CASCADE; ALTER TABLE creator_account_password DROP CONSTRAINT creator_account_password_pkey, DROP COLUMN account_id; ALTER TABLE creator_account_password RENAME COLUMN account_row_id TO account_id; ALTER TABLE creator_account_password ALTER COLUMN account_id SET NOT NULL, ADD PRIMARY KEY (account_id), ADD CONSTRAINT creator_account_password_account_id_fkey FOREIGN KEY (account_id) REFERENCES social_account(id) ON DELETE CASCADE; DROP INDEX IF EXISTS creator_account_metric_account_idx; ALTER TABLE creator_account_metric DROP COLUMN account_id; ALTER TABLE creator_account_metric RENAME COLUMN account_row_id TO account_id; ALTER TABLE creator_account_metric ADD CONSTRAINT creator_account_metric_account_collected_unique UNIQUE (account_id, collected_at), ADD CONSTRAINT creator_account_metric_account_id_fkey FOREIGN KEY (account_id) REFERENCES social_account(id) ON DELETE CASCADE; CREATE INDEX IF NOT EXISTS creator_account_metric_account_collected_idx ON creator_account_metric (account_id, collected_at); ALTER TABLE creator_competitor_share_job DROP COLUMN competitor_id; ALTER TABLE creator_competitor_share_job RENAME COLUMN competitor_row_id TO competitor_id; ALTER TABLE creator_competitor_share_job ADD CONSTRAINT creator_competitor_share_job_competitor_id_fkey FOREIGN KEY (competitor_id) REFERENCES creator_competitor(id) ON DELETE SET NULL; ALTER TABLE creator_work_metric DROP COLUMN work_id; ALTER TABLE creator_work_metric RENAME COLUMN work_row_id TO work_id; ALTER TABLE creator_work_metric ALTER COLUMN work_id SET NOT NULL, ADD CONSTRAINT creator_work_metric_work_collected_unique UNIQUE (work_id, collected_at), ADD CONSTRAINT creator_work_metric_work_id_fkey FOREIGN KEY (work_id) REFERENCES creator_work(id) ON DELETE CASCADE; ALTER TABLE creator_comment DROP COLUMN work_id; ALTER TABLE creator_comment RENAME COLUMN work_row_id TO work_id; ALTER TABLE creator_comment ALTER COLUMN work_id SET NOT NULL, ADD CONSTRAINT creator_comment_work_id_fkey FOREIGN KEY (work_id) REFERENCES creator_work(id) ON DELETE CASCADE; CREATE INDEX IF NOT EXISTS creator_comment_work_idx ON creator_comment (work_id, published_at DESC); ALTER TABLE creator_comment_rule_result DROP CONSTRAINT creator_comment_rule_result_pkey, DROP COLUMN comment_id, DROP COLUMN rule_id; ALTER TABLE creator_comment_rule_result RENAME COLUMN comment_row_id TO comment_id; ALTER TABLE creator_comment_rule_result RENAME COLUMN rule_row_id TO rule_id; ALTER TABLE creator_comment_rule_result ALTER COLUMN comment_id SET NOT NULL, ALTER COLUMN rule_id SET NOT NULL, ADD PRIMARY KEY (comment_id, rule_id), ADD CONSTRAINT creator_comment_rule_result_comment_id_fkey FOREIGN KEY (comment_id) REFERENCES creator_comment(id) ON DELETE CASCADE, ADD CONSTRAINT creator_comment_rule_result_rule_id_fkey FOREIGN KEY (rule_id) REFERENCES creator_lead_rule(id) ON DELETE CASCADE; ALTER TABLE creator_work_cover DROP CONSTRAINT creator_work_cover_pkey, DROP COLUMN work_id; ALTER TABLE creator_work_cover RENAME COLUMN work_row_id TO work_id; ALTER TABLE creator_work_cover ALTER COLUMN work_id SET NOT NULL, ADD PRIMARY KEY (work_id, variant), ADD CONSTRAINT creator_work_cover_work_id_fkey FOREIGN KEY (work_id) REFERENCES creator_work(id) ON DELETE CASCADE; -- ============ 7) creator_collection_checkpoint:文本 id 是派生值(source:sourceID:kind),无独立语义,删除; -- 换 bigint 主键,唯一业务键保持 (source_type, source_id, collection_kind) ============ ALTER TABLE creator_collection_checkpoint DROP CONSTRAINT creator_collection_checkpoint_pkey, DROP COLUMN id; ALTER TABLE creator_collection_checkpoint ADD COLUMN id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE creator_collection_checkpoint ADD PRIMARY KEY (id); -- ============ 8) creator_settings:布尔单例行主键换 bigint identity,表达式唯一索引锁定单行 ============ ALTER TABLE creator_settings DROP CONSTRAINT creator_settings_pkey, DROP COLUMN id; ALTER TABLE creator_settings ADD COLUMN id bigint GENERATED ALWAYS AS IDENTITY; ALTER TABLE creator_settings ADD PRIMARY KEY (id); CREATE UNIQUE INDEX creator_settings_singleton_idx ON creator_settings ((true));