How to Convert JSON to SQL
Paste sample JSON records, choose a table name and review the generated statements. This is a script generator, not a database connection. Test generated SQL in an isolated database before using it on important data.
Generating CREATE TABLE From JSON
CREATE TABLE generation infers columns and candidate types from examples. One sample cannot establish all future values, lengths, indexes or nullability rules. Treat the generated schema as a starting point and adapt it to your SQL dialect.
Generating INSERT Statements
INSERT statements map object fields to columns and encode row values. Confirm column names, quoting and null handling. Large batches may need splitting to fit server limits or transaction policies.
Mapping JSON Types to SQL Types
JSON strings, numbers and booleans need SQL types appropriate to the target database. Nested objects can be serialized into text or handled separately. Dates are strings until you explicitly choose and validate a date type.
Escaping Values and SQL Safety
Escaping a generated literal is not a substitute for parameterized queries in application code. Review identifiers as well as values. Do not execute generated statements without understanding the table and data they affect.
More examples and technical details
From an Array to a Table
Generating SQL from JSON is really two jobs. The first is inferring a schema: scanning every record to work out which columns exist and what type each one should be. The second is serialising the values into INSERT statements with correct quoting and escaping.
The schema is inferred from the union of keys across all records, not just the first one, because JSON arrays are frequently ragged. A key that appears in only some records still needs a column, and the records that lack it get NULL. If a key holds a number in one record and a string in another, the widening rule applies and the column becomes text, since text can hold anything.
Side by Side Example
An orders array and the DDL plus DML it generates.
JSON input
SQL output
The apostrophe in the customer name is escaped by doubling it, which is the SQL standard mechanism. The null stays a real NULL rather than the four character string.
Type Inference Mapping
| JSON type | Typical SQL type | Notes |
|---|---|---|
| String, short | VARCHAR(255) | Length chosen from the longest observed value, rounded up |
| String, long or unbounded | TEXT | Anything over a few hundred characters |
| Integer within 32 bits | INTEGER | Safe for ids and counts |
| Integer beyond 32 bits | BIGINT | Timestamps in milliseconds land here |
| Float, money-like | DECIMAL(12,2) | Never use a binary float for currency |
| Float, scientific | DOUBLE PRECISION | Measurements and ratios |
| Boolean | BOOLEAN or TINYINT(1) | MySQL has no true boolean type |
| Null only, no other values | TEXT NULL | Nothing to infer from, widen to text |
| ISO date string | DATE or TIMESTAMP | Only if you opt into date detection |
| Object | JSON, JSONB, or a child table | Depends on how you will query it |
| Array | JSON, JSONB, or a join table | Same decision, see normalisation below |
Inferred lengths are a starting point, not a contract. If your sample happens to contain no name longer than forty characters, a VARCHAR sized to that sample will reject real data later. Widen anything that a user can type into.
Dialect Differences
| Feature | MySQL | PostgreSQL | SQLite |
|---|---|---|---|
| Identifier quoting | Backticks | Double quotes | Either |
| Auto increment key | AUTO_INCREMENT | SERIAL or IDENTITY | INTEGER PRIMARY KEY |
| Boolean | TINYINT(1), 0 and 1 | Native BOOLEAN, TRUE and FALSE | Stored as 0 and 1 |
| JSON column | JSON | JSON and JSONB, JSONB preferred | TEXT with JSON functions |
| Text type | VARCHAR or TEXT | TEXT, no length penalty | TEXT, types are advisory |
| Multi-row insert | Supported | Supported | Supported since 3.7.11 |
| Upsert | ON DUPLICATE KEY UPDATE | ON CONFLICT DO UPDATE | ON CONFLICT DO UPDATE |
PostgreSQL folds unquoted identifiers to lower case while MySQL on Linux is case sensitive for table names but not column names. The simplest way to avoid ever thinking about this is to generate snake_case identifiers and never quote them.
Handling Nested Objects and Arrays
Relational tables are flat, so nested JSON forces a modelling decision. There are three options and the right one depends entirely on how you intend to query the data.
| Strategy | Result | Good when | Cost |
|---|---|---|---|
| Flatten with dot or underscore paths | address_city, address_postcode columns | Nesting is shallow and fixed | Column explosion if the shape varies |
| Store as a JSON column | One address column holding the object | Shape varies or you rarely filter on it | Indexing and joining are awkward |
| Normalise into a child table | An addresses table with a foreign key | You query, join, or aggregate on it | More work up front, more joins later |
Arrays of scalars can live in a JSON column comfortably. Arrays of objects almost always want their own table, because a line items array inside an orders row is a one to many relationship pretending not to be one. Generated SQL will usually take the JSON column route since it is the only option that never loses data, and promoting it to a proper child table is a deliberate follow up step.
A Warning About Generated SQL
Generated statements are for schema bootstrapping and seeding: creating a table from a sample payload, loading fixtures into a development database, or getting a prototype moving. That is a safe use because you control the input and you can read the output before running it.
String concatenation is never acceptable in application code. Building a query by interpolating values into a string is the definition of a SQL injection vulnerability, and escaping by hand does not save you: encodings, multi-byte characters, and dialect specific escape modes all provide ways around a naive escaper.
Never versus always
Two more habits worth keeping. Review generated DDL before you run it, since inferred types and lengths reflect one sample rather than your real domain. And add the things inference cannot see: primary keys, foreign keys, unique constraints, NOT NULL, and the indexes your queries will actually need.
Getting data into a database is one step in a longer pipeline. See the full converter collection for JSON to CSV when your loader prefers a bulk import file, JSON Schema to validate payloads before they ever reach the database, and JSON to TypeScript to type the rows in your application layer.
Standards and references
Frequently asked questions
How do I turn JSON into SQL INSERT statements?
Paste a JSON array of records and choose the INSERT output options.
Can the tool generate CREATE TABLE SQL?
Yes. Review inferred types, constraints and dialect details before using the DDL.
How are nested JSON objects handled?
Nested values may be serialized; decide whether a JSON column or normalized tables better fit your application.
Does generated SQL prevent injection by itself?
No. Use parameterized queries for runtime input and review generated SQL before execution.
Is JSON processed locally?
Yes. The generator creates text locally and does not connect to a database.