Why turn INSERT statements into JSON
Database dumps, seed files and migration scripts store data as INSERT INTO … VALUES (…) statements. That is fine for replaying into a database, but awkward when you want the rows elsewhere: as fixtures for a unit test, a mock API response, input for a script, or simply to read a few records without spinning up MySQL or PostgreSQL. This converter reads the statements directly and returns a JSON array such as [{"id": 1, "name": "Ada"}], which you can then pass to JSON to CSV or the JSON formatter.
What it reads
INSERT INTO table (columns) VALUES (…), (…)with any number of rows per statement, plus MySQLREPLACE INTOandINSERT … SET col = value, SQLiteINSERT OR REPLACE, and OracleINSERT ALL … SELECT * FROM dual.- An INSERT without a column list takes its column names from a
CREATE TABLEfor the same table earlier in the input; constraints such asPRIMARY KEY (id)are skipped. Without either, columns are namedcolumn_1,column_2… and a warning says so. - Trailing clauses like
ON CONFLICT DO NOTHING,ON DUPLICATE KEY UPDATEandRETURNINGare ignored. - Everything else (
SET NAMES,LOCK TABLES,DROP TABLE, T-SQLGO, comments and MySQL/*!…*/hints) is skipped, and an info note counts what was skipped.
Pick the right dialect
String escaping differs between databases, and guessing wrong silently changes data, so the Dialect option matters. In standard SQL, PostgreSQL, SQLite, SQL Server and Oracle, a quote inside a string is doubled ('O''Brien') and a backslash is an ordinary character. MySQL, MariaDB, BigQuery, Snowflake and Spark also treat a backslash as an escape: 'It\'s', \n for a newline, \0 for NUL. If a MySQL dump is read as standard SQL, \' ends the string early; the error then suggests switching to MySQL. PostgreSQL E'…' strings, U&'…' Unicode strings, $$…$$ dollar quoting, Oracle q'[…]' and T-SQL N'…' are decoded in every dialect that supports them.
How values map to JSON
- Numbers keep every digit.
9007199254740993and1520.50are written exactly as in the SQL, not rounded through a floating-point double, so 64-bit IDs and money values stay intact. TRUE/FALSEbecome booleans andNULLbecomes null. SQL Server stores booleans as BIT, so its1and0stay numbers.- Typed literals and casts are read through:
DATE '2026-01-01','{"a":1}'::jsonbandCAST('42' AS int)give their string or number. Concatenations such as'a' || CHAR(10) || 'b'are evaluated. - Hex and bit literals (
X'CAFE',0xCAFE,B'0101') become strings like"0xCAFE". - Anything that is not a literal, such as
NOW(),DEFAULTorprice * 2, is kept as its source text in a string, with a warning at its line and column. Nothing is dropped without telling you.
Column types are not carried over: a DATE column gives date strings, and JSON stored as text stays a string. This mirrors JSON to SQL, and converting there and back returns the same rows.
Several tables
A dump usually covers more than one table, and a single JSON array cannot say which row came from where. By default the converter stops at the first INSERT for a second table and reports its position. Turn on Group rows by table name to get an object instead, for example {"customers": [...], "orders": [...]}. Table names are compared case-insensitively, and schema-qualified names such as public.orders keep their schema. To tidy the SQL itself, use the SQL formatter.
Examples
mysqldump extract
With the MySQL dialect, ' and \n are decoded and LOCK/UNLOCK TABLES are skipped. MySQL booleans are TINYINT, so active stays 1 or 0.
LOCK TABLES `users` WRITE;
INSERT INTO `users` (`id`, `name`, `bio`, `active`) VALUES (1,'Ada','Writes \'clean\' code\nand tests',1),(2,'Linus','Kernel \\ git',0);
UNLOCK TABLES;[
{
"id": 1,
"name": "Ada",
"bio": "Writes 'clean' code\nand tests",
"active": 1
},
{
"id": 2,
"name": "Linus",
"bio": "Kernel \\ git",
"active": 0
}
]
PostgreSQL with casts and big IDs
Integers beyond 2^53 keep every digit, the jsonb cast and typed timestamp are read through, and NOW() is kept as text with a warning.
INSERT INTO public.events (id, kind, payload, created_at) VALUES
(9007199254740993, 'signup', '{"plan": "pro"}'::jsonb, TIMESTAMP '2026-03-01 09:30:00'),
(9007199254740994, 'login', NULL, NOW())
ON CONFLICT (id) DO NOTHING;[
{
"id": 9007199254740993,
"kind": "signup",
"payload": "{\"plan\": \"pro\"}",
"created_at": "2026-03-01 09:30:00"
},
{
"id": 9007199254740994,
"kind": "login",
"payload": null,
"created_at": "NOW()"
}
]
Two tables, grouped
With grouping on, the output is an object with one array per table instead of an error at the second table.
INSERT INTO customers (id, name) VALUES (1, 'Aisha Tan'), (2, 'Ben Okafor');
INSERT INTO orders (id, customer_id, total) VALUES (100, 1, 129.90);{
"customers": [
{
"id": 1,
"name": "Aisha Tan"
},
{
"id": 2,
"name": "Ben Okafor"
}
],
"orders": [
{
"id": 100,
"customer_id": 1,
"total": 129.90
}
]
}
Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
This string is never closed — the ' has no matching 'Explained | The dump uses backslash escapes (MySQL style ‘It's’) but the dialect is set to one where backslash is an ordinary character. | Set Dialect to MySQL or MariaDB, as the error hint suggests. |
This row has 3 values, but the column list has 4 columns (id, name, email, city) | A row in VALUES has more or fewer values than the INSERT names columns. | Add or remove values in the reported row so each column gets exactly one. |
These rows are for table orders, but earlier rows are for customers; one JSON array can only hold one table | The input contains INSERTs for more than one table. | Turn on “Group rows by table name”, or paste one table at a time. |
No INSERT … VALUES statements were found | The input has only SELECT, CREATE or other statements, or INSERT … SELECT, which has no literal rows. | Paste the INSERT statements, for example from mysqldump or pg_dump --inserts. |
Frequently asked questions
Which dumps work?
Output from mysqldump, MariaDB, pg_dump --inserts or --column-inserts, SQLite .dump, SQL Server “Generate Scripts” and most hand-written seed files. Use the matching dialect for string escapes.
Why are some values strings with a warning?
They are expressions rather than literals, for example NOW() or DEFAULT. Their value is only known inside the database, so the source text is kept so you can decide what to put there.
Are DECIMAL and BIGINT values rounded?
No. Number literals are copied digit for digit into the JSON, so 0.10 stays 0.10 and 64-bit integers stay exact.
Can it convert a multi-gigabyte dump?
It streams through the statements in a background worker, so tens of megabytes are fine. Very large dumps are better split per table first.