Skip to content

diff

Compare two SQL dump files to detect schema and data differences.

Alias: df (e.g., sql-splitter df old.sql new.sql)

  • Pre-deployment verification - Compare production dump with staging to catch unexpected changes
  • Migration validation - Verify that a migration produces the expected schema changes
  • Schema drift detection - Detect when databases have diverged from each other
  • Generate migration scripts - Use --format sql to create migration DDL automatically
  • Data auditing - Track row additions, deletions, and modifications between snapshots

Use validate if you only need to check a single dump’s integrity without comparison.

The diff command loads both dumps, extracts schema metadata (tables, columns, indexes, foreign keys), and compares them structurally. For data comparison, it uses primary keys to match rows efficiently - this means tables without primary keys require special handling (--allow-no-pk).

Exit codes:

  • 0 - No differences found
  • 1 - Differences detected (useful for CI gates)
  • 2 - Error during comparison
Terminal window
sql-splitter diff <OLD> <NEW> [OPTIONS]
Terminal window
# Compare two dumps (schema + data)
sql-splitter diff old.sql new.sql
# Schema-only comparison (faster, no data loading)
sql-splitter diff old.sql new.sql --schema-only
# Data-only comparison (assumes schema is identical)
sql-splitter diff old.sql new.sql --data-only

The --format sql option generates runnable DDL to transform the old schema into the new:

Terminal window
sql-splitter diff old.sql new.sql --format sql -o migration.sql

This creates ALTER TABLE, CREATE TABLE, and DROP TABLE statements. Review before running in production.

Terminal window
# Fail CI if any differences exist
sql-splitter diff production.sql staging.sql --schema-only || exit 1
# Export diff as JSON for further processing
sql-splitter diff old.sql new.sql --format json -o diff.json
Terminal window
# Compare specific tables only
sql-splitter diff old.sql new.sql --tables users,orders
# Ignore auto-updated timestamp columns
sql-splitter diff old.sql new.sql --ignore-columns "*.updated_at,*.created_at"
# Ignore column order differences (focus on types/constraints)
sql-splitter diff old.sql new.sql --ignore-order

By default, tables without PKs are skipped for data comparison. Override this behavior:

Terminal window
# Use all columns as a composite key (slower but works)
sql-splitter diff old.sql new.sql --allow-no-pk
# Or specify a custom key for specific tables
sql-splitter diff old.sql new.sql --primary-key logs:timestamp+message
FlagShortDescriptionDefault
--output-oOutput filestdout
--dialect-dSQL dialectauto-detect
--schema-onlyCompare schema onlyfalse
--data-onlyCompare data onlyfalse
--format-fOutput format: text, json, sqltext
--tables-tOnly compare these tablesall
--exclude-eExclude these tablesnone
--max-pk-entriesMax PK entries to track10,000,000
--verbose-vShow sample PK valuesfalse
--primary-keyOverride PK (format: table:col1+col2)auto
--ignore-orderIgnore column order differencesfalse
--ignore-columnsIgnore columns matching glob patternsnone
--allow-no-pkCompare tables without PK using all columnsfalse
--progress-pShow progress barfalse

Schema changes:

  • Tables added/removed
  • Columns added/removed/modified (type, nullability)
  • Primary key changes
  • Foreign key changes
  • Index changes (CREATE INDEX, inline INDEX/KEY)

Data changes:

  • Rows added/removed/modified
  • Uses PK-based comparison for efficiency
Schema Changes:
+ Table 'audit_logs' added
- Table 'temp_data' removed
~ Table 'users' modified:
+ Column 'phone' added (VARCHAR(20))
~ Column 'email' changed: VARCHAR(100) → VARCHAR(255)
Data Changes:
users: +5 added, -2 removed, ~10 modified
orders: +100 added
{
"schema": {
"tables_added": ["audit_logs"],
"tables_removed": ["temp_data"],
"tables_modified": {
"users": {
"columns_added": [{ "name": "phone", "type": "VARCHAR(20)" }],
"columns_modified": [
{ "name": "email", "old": "VARCHAR(100)", "new": "VARCHAR(255)" }
]
}
}
},
"data": {
"users": { "added": 5, "removed": 2, "modified": 10 },
"orders": { "added": 100, "removed": 0, "modified": 0 }
}
}
-- Migration script generated by sql-splitter diff
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
ALTER TABLE users MODIFY COLUMN email VARCHAR(255);
CREATE TABLE audit_logs (
id INT PRIMARY KEY,
...
);
DROP TABLE temp_data;

Diff reports many changes but I only reformatted

Section titled “Diff reports many changes but I only reformatted”

Statement ordering and formatting differences can cause noise. Normalize both dumps first:

Terminal window
sql-splitter order old.sql -o old-sorted.sql
sql-splitter order new.sql -o new-sorted.sql
sql-splitter diff old-sorted.sql new-sorted.sql

See order for details on topological sorting and handling circular dependencies.

  • Use --schema-only if you only need DDL comparison
  • Use --tables to limit scope to specific tables
  • Use --max-pk-entries to limit row tracking for data comparison

Many “Table has no primary key” warnings

Section titled “Many “Table has no primary key” warnings”

Tables without primary keys can’t be efficiently compared. Options:

  1. Skip data comparison for those tables: Default behavior, just note the warnings
  2. Use --allow-no-pk: Compare using all columns (slower, may have false positives)
  3. Specify custom keys: --primary-key logs:timestamp+source_id

The exit code indicates differences were found. Use --verbose to see details:

Terminal window
sql-splitter diff old.sql new.sql --verbose
  • validate - Validate dump integrity
  • convert - Convert between dialects
  • order - Normalize statement order for stable diffs