DevTools Hub

Search tools

Search for a developer tool

SQL

SQL Diff

Compare two CREATE TABLE schemas — added, removed, and changed columns and constraints, plus a suggested migration.

Part of the SQL Toolkit
1 table removed 1 table added 2 tables changed
Table removed.
New table.
  • plan+ VARCHAR(20) NOT NULL
  • emailtype: VARCHAR(255) → VARCHAR(320)
  • roledefault: 'user' → 'member'
  • last_login_at+ TIMESTAMP
  • chk_roleCHECK (role IN ('user', 'admin'))CHECK (role IN ('member', 'admin', 'owner'))
Suggested migration (PostgreSQL-style)
-- Best-effort PostgreSQL-style migration generated from the diff below. Review before running.

DROP TABLE legacy_sessions;
CREATE TABLE audit_events (
  id SERIAL PRIMARY KEY,
  payload JSONB NOT NULL,
  created_at TIMESTAMP NOT NULL DEFAULT now()
);
ALTER TABLE teams ADD COLUMN plan VARCHAR(20) NOT NULL DEFAULT 'free';
ALTER TABLE users ALTER COLUMN email TYPE VARCHAR(320);
ALTER TABLE users ALTER COLUMN role SET DEFAULT 'member';
ALTER TABLE users ADD COLUMN last_login_at TIMESTAMP;
ALTER TABLE users DROP CONSTRAINT chk_role;
ALTER TABLE users ADD CONSTRAINT chk_role CHECK (role IN ('member', 'admin', 'owner'));

What this checks

Paste two versions of a schema — CREATE TABLE statements, one or many per side — and see exactly what changed: tables added or removed entirely, and within tables that exist on both sides, columns added, removed, or changed (type, nullability, default value, PRIMARY KEY/UNIQUE, and REFERENCES), plus table-level constraints (PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK). This is the comparison people actually reach for a schema diff to do — a migration file against the schema it's meant to produce, or one environment's schema dump against another to catch drift.

Tables are matched by name, and columns within a matched table are matched by name too — reordering a column, or reordering table definitions in the file, doesn't register as a change. A named constraint (CONSTRAINT chk_role CHECK (...)) is matched by that name across both sides, so a changed constraint body shows up as "changed" rather than a remove-and-add pair; an unnamed constraint is matched by its exact text instead, since there's no other identity to compare it by.

What it doesn't do

This parses CREATE TABLE statements specifically — not a full SQL grammar, and not tied to one database's exact syntax. It handles the common subset shared by PostgreSQL, MySQL, and SQL Server well enough to diff real schemas (quoted identifiers in "double quotes", `backticks`, or [brackets]; inline and table-level constraints; common modifiers like AUTO_INCREMENT and IDENTITY), but it doesn't evaluate ALTER TABLE statements — if a schema is expressed as an initial CREATE TABLE plus a history of migrations, paste the fully-resolved table definitions, not the migration files themselves. Anything in a column definition this tool doesn't recognize as a structured attribute still gets caught by a raw-text fallback comparison, so a genuine difference is flagged even when it isn't specifically labeled.

The suggested migration is a starting point, not a finished script — it's reconstructed from what this tool parsed out, written in PostgreSQL-flavored ALTER TABLE syntax, and doesn't know about your actual data (an added NOT NULL column with no default will fail against existing rows, a dropped column loses data, a changed type may not be a valid implicit cast). Review it — and test it against a copy of your data — before running it anywhere real.

FAQ

Why does a renamed column show up as one removed and one added?

Because there's no reliable way to tell a rename from an unrelated remove-then-add just from two CREATE TABLE statements — both produce the exact same before/after column lists. Treat a remove-and-add pair with a similar name and the same type as a likely rename worth a second look, and adjust the generated migration to an ALTER TABLE ... RENAME COLUMN if that's actually what happened.

Why is the migration PostgreSQL-flavored specifically?

It matches the dialect SQL Explain Helper already targets on this site. The core ADD COLUMN/DROP COLUMN/ADD CONSTRAINT syntax is close to identical across most databases; the parts most likely to need adjusting for MySQL or SQL Server are ALTER COLUMN ... TYPE (different syntax per database) and default-value expressions like now().

Does this validate the SQL itself?

No — it only extracts structure to compare, and skips (with a warning) anything it can't parse as a column or constraint. For catching syntax mistakes in a query, use SQL Query Validator.

Related tools