# DDL Migrations: Constraint & Structural Operations Step-by-step migration patterns for constraint changes, primary key modifications, and column transformations. **MUST read [overview.md](overview.md) first** for destructive operation warnings and the common verify & swap pattern. --- ## ADD CONSTRAINT Migration **Goal:** Add a constraint (UNIQUE, CHECK) to an existing table. ### Pre-Migration Validation **MUST validate existing data satisfies the new constraint.** ```sql -- For UNIQUE constraint: check for duplicates SELECT target_column, COUNT(*) as cnt FROM target_table GROUP BY target_column HAVING COUNT(*) > 1 LIMIT 10; -- MUST ABORT if any duplicates exist -- For CHECK constraint: validate all rows pass SELECT COUNT(*) as invalid_count FROM target_table WHERE NOT (check_condition); -- MUST ABORT if invalid_count > 0 ``` ### Migration Steps #### Step 1: Create new table with the constraint ```sql CREATE TABLE target_table_new ( id UUID PRIMARY KEY, email VARCHAR(255) UNIQUE, -- Added UNIQUE constraint age INTEGER CHECK (age >= 0), -- Added CHECK constraint other_column TEXT ); ``` #### Step 2: Copy data ```sql INSERT INTO target_table_new (id, email, age, other_column) SELECT id, email, age, other_column FROM target_table; ``` **Step 3: Verify and swap** (see [Common Pattern](overview.md#common-verify--swap-pattern)) --- ## DROP CONSTRAINT Migration **Goal:** Remove a constraint (UNIQUE, CHECK) from a table. ### Pre-Migration Validation ```sql -- Identify existing constraints SELECT constraint_name, constraint_type FROM information_schema.table_constraints WHERE table_name = 'target_table' AND constraint_type IN ('UNIQUE', 'CHECK'); ``` ### Migration Steps #### Step 1: Create new table without the constraint ```sql CREATE TABLE target_table_new ( id UUID PRIMARY KEY, email VARCHAR(255), -- Removed UNIQUE constraint other_column TEXT ); ``` #### Step 2: Copy data ```sql INSERT INTO target_table_new (id, email, other_column) SELECT id, email, other_column FROM target_table; ``` **Step 3: Verify and swap** (see [Common Pattern](overview.md#common-verify--swap-pattern)) --- ## MODIFY PRIMARY KEY Migration **Goal:** Change which column(s) form the primary key. ### Pre-Migration Validation **MUST validate new PK column has unique, non-null values.** ```sql -- Check for duplicates SELECT new_pk_column, COUNT(*) as cnt FROM target_table GROUP BY new_pk_column HAVING COUNT(*) > 1 LIMIT 10; -- MUST ABORT if any duplicates exist -- Check for NULLs SELECT COUNT(*) as null_count FROM target_table WHERE new_pk_column IS NULL; -- MUST ABORT if null_count > 0 ``` ### Migration Steps #### Step 1: Create new table with new primary key ```sql CREATE TABLE target_table_new ( new_pk_column UUID PRIMARY KEY, -- New PK old_pk_column VARCHAR(255), -- Demoted to regular column other_column TEXT ); ``` #### Step 2: Copy data ```sql INSERT INTO target_table_new (new_pk_column, old_pk_column, other_column) SELECT new_pk_column, old_pk_column, other_column FROM target_table; ``` **Step 3: Verify and swap** (see [Common Pattern](overview.md#common-verify--swap-pattern)) --- ## Column Transformations (Split/Merge) ### Split Column **Goal:** Split one column into multiple (e.g., `full_name` → `first_name` + `last_name`). ```sql -- Create new table with split columns CREATE TABLE target_table_new ( id UUID PRIMARY KEY, first_name VARCHAR(255), last_name VARCHAR(255) ); -- Copy with transformation INSERT INTO target_table_new (id, first_name, last_name) SELECT id, SPLIT_PART(full_name, ' ', 1), SUBSTRING(full_name FROM POSITION(' ' IN full_name) + 1) FROM target_table; -- Verify, swap, re-index (see Common Pattern) ``` ### Merge Columns **Goal:** Combine multiple columns into one (e.g., `first_name` + `last_name` → `display_name`). ```sql -- Create new table with merged column CREATE TABLE target_table_new ( id UUID PRIMARY KEY, display_name VARCHAR(512) ); -- Copy with concatenation INSERT INTO target_table_new (id, display_name) SELECT id, CONCAT(COALESCE(first_name, ''), ' ', COALESCE(last_name, '')) FROM target_table; -- Verify, swap, re-index (see Common Pattern) ```