Copy values from one column to another in the same table
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Copying data from one column to another in the same table is a common migration task, but the risk is usually operational rather than syntactic. A single unscoped update can overwrite trusted values or lock a hot table for too long. A safe approach is to preview affected rows, apply guarded updates, verify outcomes, and only then finalize constraints.
Basic Update Pattern
The core statement is simple:
This copies email into backup_email for every row. It is correct for full-table backfill, but in production most updates should be narrowed with explicit conditions.
A safer first version is:
This avoids overwriting existing values and makes retries idempotent.
Preview and Count Before Updating
Before changing data, preview representative rows and count impact. These two checks catch most filter mistakes.
If the count is unexpectedly large, stop and re-check predicates. Never treat a mass update as harmless just because the query is short.
Use Transactions for Safety
Wrap the operation in a transaction when your engine and workload allow it.
If validation fails, run ROLLBACK instead of commit. This gives you a clean escape hatch during migrations.
Copy with Transformation
Sometimes the destination column has different format requirements. You can transform in the same update as long as the transformation is deterministic and reviewed.
Another common case is explicit casting between numeric and text columns:
Avoid relying on implicit conversion when portability matters.
Large Tables and Batch Backfill
On large tables, one giant update can hold locks too long or create replication lag. Batch by key range or timestamp window.
Then repeat with the next range. Between batches, monitor lock waits, query latency, and replica delay. Batching is slower in wall-clock time but safer for live systems.
A practical rollout pattern:
- Add new nullable column.
- Backfill in batches.
- Verify no missing values.
- Switch reads and writes to new column.
- Add
NOT NULLor default constraints.
This staged method is easier to recover than one all-in migration.
Database-Specific Notes
The SQL pattern is universal, but behavior differs by engine.
- PostgreSQL can return changed rows via
RETURNINGfor auditing. - SQL Server might need careful indexing to avoid lock escalation on large updates.
- MySQL behavior can vary with storage engine and transaction settings.
If your update must run online, test on staging with production-like row counts and indexes.
Validate After the Update
Do not stop at affected-row count from the update command. Run targeted checks.
For engines without IS DISTINCT FROM, use explicit null-aware checks. Also spot-check a sample by primary key and record the migration id in an operations log.
Common Pitfalls
The most frequent failure is forgetting a WHERE clause and updating the entire table accidentally. Another is overwriting curated target values because the query did not include target_column IS NULL. Teams also run into long lock windows by executing one huge update on hot tables instead of batching. A less obvious issue is silent type coercion, where copied values are truncated or reformatted unexpectedly. Finally, skipping post-update validation makes rollback decisions blind.
Summary
- Use
UPDATE ... SET target = sourceas the base pattern, then add strict predicates. - Preview rows and count impact before making changes.
- Run updates in transactions and validate before commit.
- Batch large backfills to reduce operational risk.
- Validate data correctness after update, not only affected-row counts.

