Origineel SQL
Gewijzigd SQL

SQL Diff: vergelijk twee SQL-bestanden online

Plak, formatteer en vergelijk twee SQL-queries of schema-bestanden naast elkaar. Werkt voor PostgreSQL, MySQL, SQL Server, SQLite en Oracle.

Wat is de SQL-diff-tool?

Een gratis tool in de browser om twee SQL-bestanden te vergelijken. Plak een oude CREATE TABLE links, de nieuwe rechts, en de wijzigingen lichten teken voor teken op. Dezelfde flow voor twee versies van een analytics-query, een door een ORM gegenereerd statement, of een pg_dump-uitvoer. Niets verlaat je machine.

De diff werkt op tekstniveau. Hij parseert de SQL niet tot een AST en begrijpt geen semantische gelijkheid: SELECT a, b en SELECT b, a ogen verschillend voor de diff, ook al geven beide dezelfde rijen in een andere volgorde terug. Voor 95% van de code-reviewtaken (schemamigraties, query-refactors, vergelijking van ORM-uitvoer) is een tekst-diff precies wat je wilt, omdat de volgorde van kolommen en clausules deel uitmaakt van hoe het team de wijziging leest.

Als je ooit hebt geprobeerd de ene nieuwe WHERE-clausule te vinden in een analytics-query van 400 regels die plotseling een ander aantal rijen teruggaf, dan is dit de tool die je er in seconden brengt. Voor niet-SQL-tekst is onze tekst-diff-tool de juiste keuze. Voor ORM-resultaten in JSON behandelt JSON-diff de herordening van objecten netter. Voor oude DDL-exports geschreven als XML-metadata past XML-diff beter.

Hoe de diff daadwerkelijk werkt

Onder de motorkap draait de diff op karakterniveau, en daarna verschuift een semantische pass de markeringen zodat ze op identifiers, sleutelwoorden en clausulesgrenzen vallen in plaats van op willekeurige interpunctie. Toevoegingen verschijnen rechts in groen, verwijderingen links in rood. Elk paneel heeft een Format-knop die de SQL herschikt met consistente inspringing en één statement per regel, wat de meeste opmaakruis al wegneemt vóór de vergelijking.

SQL is een familie van dialecten, geen enkele taal. De ISO/IEC 9075-standaard definieert een kerngrammatica, maar elke database breidt die uit: PostgreSQL heeft dollar-quoted strings en RETURNING, MySQL heeft backtick-identifiers en ON DUPLICATE KEY UPDATE, SQL Server gebruikt TOP en identifiers tussen vierkante haken, SQLite tolereert bijna alles, en Oracle heeft ROWNUM en CONNECT BY. Diffen tussen dialecten is prima; de tool waarschuwt niet dat een fragment in een van die dialecten ongeldig is.

Het andere wat je moet weten: de tekst van een query vergelijken is niet hetzelfde als de plannen vergelijken. Twee statements met identieke tekst kunnen bij andere statistieken zeer verschillende plannen opleveren, en twee cosmetisch verschillende statements kunnen identieke plannen geven. Voor planvergelijking zijn EXPLAIN ANALYZE in psql of het equivalent in je databaseclient (DataGrip, DBeaver, SSMS) de juiste tools. Voor tekst-refactor-review is de diff wat je wilt. Achtergrondinfo over de taal zelf staat op Wikipedia.

SQL vergelijken in drie stappen

Twee tekstpanelen, één diff. Geen aanmelding, geen upload, geen server-roundtrip.

  1. 1

    Plak of upload je SQL

    Plak de oude SQL links, de nieuwe rechts. Of klik aan een van beide kanten op Uploaden om een .sql-, .ddl- of .psql-bestand direct te laden. De Sample-knop vult beide panelen met een klein orders-schemavoorbeeld als je de tool eerst in actie wilt zien.

  2. 2

    Formatteer beide kanten voor een eerlijke vergelijking

    Klik op Format op elk paneel om de SQL te herformatteren met consistente inspringing, één statement per regel en sleutelwoorden in hoofdletters. Dit doodt de ruis van een door DataGrip geformatteerde query aan de ene kant en een handgetypte aan de andere, zodat de diff echte schema- en clausule-veranderingen markeert in plaats van witruimte- en hoofdletterverschillen.

  3. 3

    Lees de diff

    Verwijderingen verschijnen met een rode markering links, toevoegingen met een groene markering rechts. Scroll aan de ene kant en de andere volgt. De wijzigingstellers in elke header vertellen je hoeveel afzonderlijke bewerkingen de diff heeft gevonden over kolommen, joins, predikaten en DDL-elementen.

Wanneer SQL-diff de juiste tool is

Een schemamigratie reviewen vóór toepassing

Een migratie-PR voegt drie kolommen toe en past twee indexen aan. Plak de vorige CREATE TABLE tegen de nieuwe en de toevoegingen springen eruit: er is een kolom currency CHAR(3) NOT NULL toegevoegd zonder DEFAULT, wat zal falen op elke bestaande rij. Dat opvangen vóór de migratie tegen prod draait, in plaats van nadat het deployment-alarm om 2 uur 's nachts afgaat, is precies de bedoeling van deze workflow. Zelfde waarde voor ALTER TABLE-statements waarbij een kolomtype versmalt van VARCHAR(255) naar VARCHAR(50).

Diff van twee versies van een analytics-query

Een rapportagequery die gisteren 12.400 rijen gaf, geeft er vandaag 8.900. Diff de query van gisteren tegen die van vandaag en de schuldige verandering komt boven: een LEFT JOIN is stilletjes een INNER JOIN geworden, of er is door iemand die het dashboard wilde opschonen een WHERE status <> 'cancelled' bijgezet. De tekst-diff brengt je in seconden bij de regel, terwijl beide queries naast elkaar lezen in Slack tien minuten zou kosten.

ORM-gegenereerde SQL vergelijken tussen app-versies

Na een Hibernate- of SQLAlchemy-upgrade zijn queries die uit drie joins bestonden er nu vier met extra subqueries, of is parameterbinding van ? overgegaan naar $1-placeholders. Vang de SQL uit je query-log op elke app-versie (psql log_statement = all, MySQL slow log of je APM-tool) en diff ze. De aliasnamen zullen ruizig zijn (t1, t2, generatedAlias0), maar de werkelijke structurele verandering is meestal het enige wat de diff als echte bewerking markeert.

Valideren dat een DDL-refactor de bedoeling behoudt

Je hebt user_orders hernoemd naar orders en een JSON-blob-kolom in genormaliseerde tabellen gesplitst. Plak de uitvoer van pg_dump --schema-only voor en na de refactor; de diff maakt duidelijk of je elke constraint, index en default hebt behouden. De valkuil om in de gaten te houden is een NOT NULL die stilletjes verdween bij de hernoeming, of een UNIQUE-constraint die wegviel omdat niemand hem opnieuw aan de nieuwe tabel toevoegde.

Controleren of het staging-schema overeenkomt met prod

Draai pg_dump --schema-only --no-owner tegen staging en prod, en diff de twee. De verschillen zouden precies de migraties moeten zijn die in de wachtrij staan voor de volgende deploy. Al het andere, een extra index, een ander kolomtype, een vergeten testtabel, is een teken van schema-drift die bij de echte deploy zal bijten. Zelfde aanpak met mysqldump --no-data voor MySQL en SCRIPT TO voor SQL Server, of DataGrips schema-export voor elke database.

Dialectportering reviewen (Postgres naar MySQL)

Een query van PostgreSQL naar MySQL of andersom porteren betekent bijhouden welke functies, types en clausules moeten veranderen: SERIAL versus AUTO_INCREMENT, NOW() versus CURRENT_TIMESTAMP, RETURNING versus LAST_INSERT_ID(). Diff het origineel tegen de geporteerde versie en alle dialect-substituties komen naar boven. De diff valideert de SQL niet op het doel-dialect, dus laat hem alsnog door psql of mysql lopen ter bevestiging, maar de regel-voor-regel-weergave vertelt je welke beslissingen je dubbel moet checken.

SQL quick reference

Een korte spiekbrief voor de dialect- en parsing-randgevallen die deze diff het vaakst aan de oppervlakte brengt. Gestoeld op de ISO SQL-standaard en de docs van de grote leveranciers.

TopicWhat this tool does
Dialect-driftPostgreSQL, MySQL, SQL Server, SQLite en Oracle breiden elk de ISO SQL-standaard uit met eigen syntaxis. SERIAL, AUTO_INCREMENT, IDENTITY en GENERATED ALWAYS AS IDENTITY zijn vier manieren om hetzelfde idee op te schrijven.
Identifier case foldingPostgreSQL vouwt niet-gequote identifiers naar kleine letters, dus Users en users zijn dezelfde tabel. MySQL hangt af van lower_case_table_names en het onderliggende bestandssysteem. SQL Server is standaard hoofdletter-ongevoelig maar respecteert de collation. Quote identifiers met "Users" (standaard), backticks (MySQL) of vierkante haken (SQL Server) om de casus te behouden.
Sleutelwoord-casusSQL-sleutelwoorden zijn overal hoofdletter-ongevoelig, dus SELECT en select zijn voor de parser identiek. De conventie is hoofdletters voor sleutelwoorden en kleine letters voor identifiers; de meeste styleguides en de ISO-spec volgen dit. Gemengde casus is geldig en draait, maar tools als sqlfluff en sqlfmt normaliseren het.
CommentaarstijlenTwee vormen: -- regelcommentaar (eindigt aan het einde van de regel) en /* blokcommentaar */ (geen nesting in standaard-SQL, hoewel sommige dialecten het toelaten). MySQL ondersteunt ook # voor regelcommentaren als uitbreiding. De diff behandelt commentaren als tekst en toont commentaarwijzigingen als elke andere wijziging.
Statement-scheidersDe puntkomma (;) beëindigt een statement in standaard-SQL. De meeste clients vereisen hem tussen statements in een script. Sommige clients (SSMS) gebruiken in plaats daarvan GO als batch-scheider, wat geen onderdeel van de SQL-grammatica is; het is een client-directive.
Dollar-quoted strings (PostgreSQL)PostgreSQL ondersteunt $tag$ ... $tag$ voor string-literalen zodat je enkele aanhalingstekens binnenin niet hoeft te escapen, vooral handig voor functielichamen. $$ SELECT 'hello' $$ is geldig en gebruikelijk in CREATE FUNCTION-blokken. Andere dialecten parseren deze syntaxis niet.
Parameter-binding-placeholdersGeen standaard. PostgreSQL en ORMs die erop richten gebruiken $1, $2. JDBC, MySQL en ODBC gebruiken ?. Genoemde placeholders :name zijn gebruikelijk in Oracle en in veel ORM-stringtemplates. Door ORM gegenereerde SQL verschilt tussen versies vaak alleen in placeholder-stijl; formatteer beide kanten vóór de diff.
EncodingUTF-8 is in 2026 de universele default voor SQL-bestanden. Oudere scripts uit Windows-bron kunnen nog opgeslagen zijn als UTF-16 LE met een BOM, wat als spookkarakter op regel 1 van een tekst-diff verschijnt. Als twee bestanden er identiek uitzien maar de diff een wijziging van één teken aan het begin meldt, vermoed dan de BOM en sla opnieuw op als expliciet UTF-8.

SQL-diff: veelgestelde vragen

Wat is het verschil met EXPLAIN ANALYZE op beide queries draaien?

Andere laag van de stack. EXPLAIN ANALYZE laat je het plan van de query zien, wat de optimizer heeft besloten te doen gegeven de statistieken die hij heeft. Deze tool diff de tekst van de query, dat is wat in je repo veranderde. Meestal wil je beide: deze diff om de refactor te spotten (een join-type is veranderd, een predikaat is verschoven), en daarna EXPLAIN ANALYZE in psql of je client om te bevestigen dat de optimizer een verstandig plan heeft gekozen voor de nieuwe vorm. De twee zijn complementair, geen vervanging.

Is de diff dialect-bewust (PostgreSQL vs MySQL vs SQL Server)?

Nee. De diff behandelt de invoer als tekst, dus parseert PostgreSQL, MySQL, SQL Server, SQLite of Oracle niet anders en markeert geen dialect-incompatibele syntaxis. Dat is met opzet: het betekent dat je tussen dialecten kunt diffen, wat precies is wat je wilt bij het porteren van een query. Heb je dialect-bewuste linting nodig, jaag de SQL dan apart door sqlfluff of de parser van je database. Voor de review-use case ("wat is er in deze query veranderd") is tekstniveau de juiste granulariteit.

Formatteert de tool SQL voor mij?

Ja, de Format-knop op elk paneel herformatteert de SQL met consistente inspringing, sleutelwoorden in hoofdletters en één statement per regel. Het is een basale formatter, geen vervanging voor sqlfmt of sqlfluff: hij herschrijft impliciete joins niet naar expliciete, en hij dwingt geen styleguide van een specifiek dialect af. Het doel is opmaakruis te elimineren vóór de diff, zodat een door DataGrip geformatteerde query aan de ene kant en een handgetypte aan de andere netjes te vergelijken zijn.

Normaliseert hij de hoofdlettering van sleutelwoorden (SELECT vs select)?

De Format-knop zet sleutelwoorden in hoofdletters, wat de conventie is in de meeste styleguides en in de ISO SQL-standaard. Klik je niet op Format, dan komt gemengde casus naar boven als diff omdat de onderliggende engine karakter-gebaseerd is. SQL-sleutelwoorden zijn in elke database hoofdletter-ongevoelig, dus select en SELECT draaien identiek. Identifier-casus is een andere kwestie en verschilt per database; zie de quick reference hieronder voor hoe Postgres, MySQL en SQL Server uiteenlopen.

Hoe ga ik om met door ORM gegenereerde aliassen zoals t1, t2, generatedAlias0?

ORM-uitvoer is van nature ruizig: Hibernate genereert generatedAlias0, generatedAlias1, en SQLAlchemy gebruikt anon_1, anon_2. Als twee ORM-versies dezelfde aliassen in een andere volgorde toewijzen, markeert de tekst-diff elke alias-omwisseling als wijziging, ook al is de query structureel identiek. De praktische oplossing is beide kanten te formatteren, alleen-aliasverschillen te negeren (meestal duidelijk als gepaarde rode en groene blokken op dezelfde regel) en je te richten op de echte structurele bewerkingen: een nieuwe join, een andere WHERE-clausule, een verwijderde kolom.

Zijn er groottelimieten voor de SQL die ik plak?

Zachte limieten, geen harde. De diff draait in je browser, dus de bovengrens is het geheugen van je browser en hoelang je bereid bent te wachten. Een pg_dump-uitvoer van 5.000 regels diff in ruim onder een seconde op een moderne laptop. Een dump van 200.000 regels kan meerdere seconden kosten en geheugengrenzen raken op zwakkere apparaten. Voor zulke grote database-dumps is de juiste flow eerst alleen het schema diffen (pg_dump --schema-only) en daarna inzoomen op specifieke tabellen als je een vergelijking op dataniveau nodig hebt.

Privacy en hoe het werkt

Je SQL verlaat je browser nooit. De formatter en de diff draaien beide op je machine, lokaal. Geen analytics op je invoer, geen logs, geen "behulpzame" cloud-roundtrip, wat ertoe doet wanneer de SQL die je plakt echte tabelnamen, echte kolomnamen of echte productiedata in een voorbeeldrij bevat. De taal is gedocumenteerd in ISO/IEC 9075, en de dialect-referenties zijn PostgreSQL, MySQL, SQL Server en SQLite.