Each key becomes a column, collected from every row rather than the first, so a field only some records have still gets a column and is NULL elsewhere. The type comes from all of a column’s values. Integers are INTEGER, BIGINT past 32 bits and NUMERIC or DECIMAL past 64, and the digits are copied from the JSON text rather than a JavaScript number, so an id like 12345678901234567890 arrives intact. Decimals are NUMERIC in PostgreSQL, a DECIMAL sized to the data in MySQL and SQL Server, and REAL in SQLite. Booleans are BOOLEAN in PostgreSQL, TINYINT(1) in MySQL, 0 and 1 in SQLite and BIT in SQL Server. Nested objects and arrays go into one JSON column, JSONB, JSON, TEXT or NVARCHAR(MAX), unless Flatten turns them into columns such as address_city. A string column becomes DATE or a timestamp only when every value is an ISO 8601 date or date-time; one stray "yesterday" keeps it text, and when most values parse the result names the row that does not. MySQL’s DATETIME has no time zone and refuses a Z, so offsets are converted to UTC for it.
Every value is written into the SQL as a literal, so the escaping is what has to be right: a quote or backslash handled the wrong way for the database corrupts the value, or ends the string early and runs the rest as SQL. Quotes are doubled in all four, and the backslash is where they differ. PostgreSQL, SQLite and SQL Server treat it as an ordinary character, but a PostgreSQL string holding one is written E'…' with it doubled, which reads the same whatever standard_conforming_strings is set to. MySQL treats it as an escape by default, so it is doubled; if your server runs with NO_BACKSLASH_ESCAPES, say so and only quotes are doubled. SQL Server strings are N'…', since without the N non-ASCII text is converted to the database’s code page, and a line break straight after a backslash, which T-SQL reads as a line continuation and deletes, is written as NCHAR(10). No literal holds a raw carriage return, because the mysql and sqlite3 command-line clients drop one at the end of a line. A NUL character or an unpaired surrogate is refused.
Column names are snake_case by default, so userId becomes user_id: PostgreSQL folds unquoted names to lower case, and a column created as "userId" has to be quoted in every query from then on. Keep key names uses the keys as written. Names are always quoted, so a column called order or select works, and are cut to each database’s limit, 63 bytes in PostgreSQL, 64 characters in MySQL and 128 in SQL Server, then made unique ignoring case. The table name can be schema.table. Rows per INSERT is 100 by default and at most 1,000, SQL Server’s limit for one VALUES list. JSON Lines, one object per line, is read as rows, and a single object becomes one row. Not written: primary keys, NOT NULL, indexes, DROP TABLE and upserts, which depend on your schema.