Subchapter 63.7
references/ddl-migrations/column-operations.mdMarkdown5 KBView on GitHub
Step-by-step migration patterns for column-level changes using the Table Recreation Pattern.
MUST read overview.md first for destructive operation warnings and the common verify & swap pattern.
Goal: Remove a column from an existing table.
SELECT COUNT(*) as total_rows FROM target_table;
SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name = 'target_table' ORDER BY ordinal_position;CREATE TABLE target_table_new (
id UUID PRIMARY KEY,
tenant_id VARCHAR(255) NOT NULL,
kept_column1 VARCHAR(255),
kept_column2 INTEGER
-- dropped_column is NOT included
);INSERT INTO target_table_new (id, tenant_id, kept_column1, kept_column2)
SELECT id, tenant_id, kept_column1, kept_column2
FROM target_table;For tables > 3,000 rows, use Batched Migration Pattern.
Step 3: Verify and swap (see Common Pattern)
Goal: Change a column’s data type.
MUST validate data compatibility BEFORE migration to prevent data loss.
-- Example: VARCHAR to INTEGER - check for non-numeric values
SELECT COUNT(*) as invalid_count FROM target_table
WHERE column_to_change !~ '^-?[0-9]+$';
-- MUST abort if invalid_count > 0
-- Show problematic rows
SELECT id, column_to_change FROM target_table
WHERE column_to_change !~ '^-?[0-9]+$' LIMIT 100;| From Type | To Type | Validation |
|---|---|---|
| VARCHAR | INTEGER | MUST validate all values are numeric |
| VARCHAR | BOOLEAN | MUST validate values are ‘true’/’false’/’t’/’f’/’1’/’0’ |
| INTEGER | VARCHAR | Safe conversion |
| TEXT | VARCHAR(n) | MUST validate max length ≤ n |
| TIMESTAMP | DATE | Safe (truncates time) |
| INTEGER | DECIMAL | Safe conversion |
CREATE TABLE target_table_new (
id UUID PRIMARY KEY,
converted_column INTEGER, -- Changed from VARCHAR
other_column TEXT
);INSERT INTO target_table_new (id, converted_column, other_column)
SELECT id, CAST(converted_column AS INTEGER), other_column
FROM target_table;Step 3: Verify and swap (see Common Pattern)
Goal: Change a column’s nullability constraint.
SELECT COUNT(*) as null_count FROM target_table
WHERE target_column IS NULL;
-- MUST ABORT if null_count > 0, or plan to provide default valuesCREATE TABLE target_table_new (
id UUID PRIMARY KEY,
target_column VARCHAR(255) NOT NULL, -- Changed from nullable
other_column TEXT
);INSERT INTO target_table_new (id, target_column, other_column)
SELECT id, COALESCE(target_column, 'default_value'), other_column
FROM target_table;Step 3: Verify and swap (see Common Pattern)
Goal: Add or remove a default value for a column.
SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name = 'target_table' ORDER BY ordinal_position;
-- Identify current column definition and any existing defaultsCREATE TABLE target_table_new (
id UUID PRIMARY KEY,
status VARCHAR(50) DEFAULT 'pending', -- Added default
other_column TEXT
);INSERT INTO target_table_new (id, status, other_column)
SELECT id, status, other_column
FROM target_table;Step 3: Verify and swap (see Common Pattern)
CREATE TABLE target_table_new (
id UUID PRIMARY KEY,
status VARCHAR(50), -- Removed DEFAULT
other_column TEXT
);INSERT INTO target_table_new (id, status, other_column)
SELECT id, status, other_column
FROM target_table;Step 3: Verify and swap (see Common Pattern)