-- Migration: Fix deduplication constraints and clean up duplicate rows -- 1. Deduplicate attachments DELETE FROM attachment a USING attachment b WHERE a.announcement_id = b.announcement_id AND a.url = b.url AND a.id > b.id; -- 2. Unique constraint for attachment idempotency DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'uq_attachment_announcement_url' ) THEN ALTER TABLE attachment ADD CONSTRAINT uq_attachment_announcement_url UNIQUE (announcement_id, url); END IF; END $$; -- 3. Fix invalid self-referencing canonical_id UPDATE announcement SET canonical_id = NULL WHERE canonical_id = id; -- 4. Clean duplicate positions and add unique index DELETE FROM position a USING position b WHERE a.announcement_id = b.announcement_id AND a.post_name = b.post_name AND COALESCE(a.dept, '') = COALESCE(b.dept, '') AND a.id > b.id; CREATE UNIQUE INDEX IF NOT EXISTS uq_position_announcement_post_dept ON position (announcement_id, post_name, COALESCE(dept, ''));