使用方法
- 「SQL 源文本」默认已经写好一条三组值的 INSERT:第一组含双引号与 NOW(),第二组含两个连续单引号与 NULL,第三组含反斜杠 n 与 UUID()。
- 点「转为JSON」或在文本框里按 Ctrl+Enter(Mac 是 Cmd+Enter)完成转换;在「省略列名时的键前缀」输入框里按回车同样触发。
- 「省略列名时的键前缀」默认 col。遇到 INSERT INTO t VALUES (...) 这种没写列名的语句,键会取 col1、col2、col3;想换成 f1、c1 之类的前缀直接改这一栏。
- 「多条 INSERT 的输出方式」默认每条语句一个数组:粘贴三段 INSERT 会按顺序输出三个数组,彼此空一行;改成合并则所有语句的所有行摊进一个扁平数组。
- 「输出缩进空格数」默认 2,可填 0 到 8 的整数;填 0 输出压缩成一行,方便比较两份 seed 数据的差异,填 4 更贴近常见编辑器的保存宽度。
- 结果区第一行是统计摘要:语句条数、对象数、涉及的表、未求值函数清单与四类值的计数;下面是输出原文,「复制结果」复制的就是它。
- 输入框被清空时点「转为JSON」会自动填回示例;本页不联网,也不写 localStorage,刷新即恢复默认。
- 下方是二十行值形态对照表,默认显示 12 行,点「加载更多」看余下 8 行;「导出 CSV」存成带字节序标记的文件,「复制对照表」复制成制表符分隔文本。
这个SQLInsert转JSON转换器能解决什么
把数据库导出脚本里的 INSERT 语句搬进前端或测试工具时,最常见的做法是复制粘贴成对象字面量,手工做既慢又容易错。这个SQLInsert转JSON转换器做的是按 SQL 的词法规则把语句解析成结构化数据:有几组括号就输出几个对象,一整条语句输出一个数组,多组多列都能一次转完。
第一类场景是 seed 数据搬运。测试夹具、演示数据、题库常常以 INSERT 脚本形式存在,转成 JSON 后可以直接被前端 mock、Node 脚本或配置中心消费。字符串里的逗号、括号、单引号都会被正确处理,不会把一条记录切成两半。
第二类场景是数据体检。列数和值数不一致、字符串引号没闭合、混进了 SELECT 语句,这些在成千上万行导出脚本里很难肉眼发现。本页的每条报错都带「第几条语句、第几组、第几个值」的定位,并说明原因,不用人工数行。
边界也要说清:本页只解析 INSERT ... VALUES 这一种形态,不支持 INSERT ... SELECT、ON DUPLICATE KEY UPDATE、多表 INSERT 与存储过程;函数调用一律不求值,只保留原文。要执行 SQL 或做库级迁移,请使用数据库客户端。
扫描与类型推断原理
解析分四步。第一步剥离注释:扫描时维护「是否在单引号字符串内」,字符串外的 -- 到行尾与 /* */ 块注释被删掉,并用一个空格替代,避免把两侧的符号粘成一个 token;字符串里的 -- 与 /* */ 原样保留。第二步按分号切语句,同样只在字符串外切。第三步解析每条语句的 INSERT INTO 表名、可选列名与 VALUES 之后的若干组括号,组与组之间用逗号分隔。
第四步是核心:切分一组里的各个值。这里必须用认得引号状态的扫描器——按逗号切分会把 'a, b' 切成两半,按括号切分会把 'a)b' 截断。扫描器在字符串内时只认两种特殊形态:两个连续单引号(SQL 标准的字面单引号转义)与反斜杠转义,其余字符连同逗号、括号一起吞掉;在字符串外时才记录括号深度,只在深度 0 的逗号处断开。
类型推断按值的形态决定:匹配数字正则(含负数、小数、科学计数法)的转 number;NULL 转 null;TRUE 与 FALSE 转布尔,三者都不区分大小写;以单引号开头的是字符串,其中的 \n、\t、\\、\' 被还原,'' 还原成一个单引号;形如标识符加左括号的(NOW()、UUID())判定为函数调用,保留原文字符串并在摘要里列出,不假装算出一个值;其余裸词按字符串原样保留。
表名支持三种包裹符:反引号(MySQL)、方括号(SQL Server)、双引号(PostgreSQL),解析时剥掉外壳只留名字。列名同样剥掉外壳。输出 JSON 时不带字节序标记。
| 变量 | 含义 | 取值 | 影响 |
|---|---|---|---|
| pre | 省略列名时的键前缀 | 合法标识符 | 键名为前缀加序号,从 1 起 |
| multi | 多语句输出方式 | split / merge | split 按语句分开,merge 摊平 |
| ind | 输出缩进空格数 | 0 ~ 8 的整数 | 0 表示压缩成一行 |
| iq | 单引号状态 | true 表示处于字符串内 | 为 true 时逗号与括号不当分隔符 |
| depth | 括号深度 | 非负整数 | 只在深度 0 处按逗号拆值 |
完整示例
默认源文本是一条三组值的 INSERT。逐组看:第一组的 bio 里有一对双引号,它在单引号字符串内,是普通字符;created 是 NOW(),保留原文。第二组的 bio 写了两个连续单引号,还原成一个单引号,得到 "It's fine";score 是 NULL,转成 null。第三组的 bio 里是反斜杠 n,还原成真换行;created 是 UUID(),同样保留原文。
-- 用户表批量插入 → 行注释,整段剥离 INSERT INTO `users` (id, name, bio, score, active, created) VALUES (1, 'Alice', 'She said "hi"', 95.5, TRUE, NOW()), → 第 1 组,6 个值 (2, 'Bob', 'It''s fine', NULL, FALSE, '2024-01-02 …'), → 第 2 组,'' 是字面单引号 (3, 'Carol', 'line1\nline2', 0, NULL, UUID()); → 第 3 组,反斜杠 n 是真换行
输出是一个含三个对象的数组,对象键就是列名 id、name、bio、score、active、created。把「多条 INSERT 的输出方式」改成合并,再粘贴第二条 INSERT,两个语句的六行会摊进同一个数组;保持分开则输出两个数组,彼此空一行。把「省略列名时的键前缀」改成 f,第三行那种没写列名的语句就会得到 f1、f2 这样的键。
值形态对照表
下表列出二十种 SQL 写法经过本页解析后的结果,由页面自己的解析器逐条算出,前十二行直接展开,点工具区的「加载更多」看余下八行。报错行给出的是完整错误文案。
| 源语句 | 解析结果 | 说明 |
|---|---|---|
| INSERT INTO t (a) VALUES (1); | [{"a":1}] | 一组一值 |
| INSERT INTO t (a,b) VALUES (1,'x'),(2,'y'); | [{"a":1,"b":"x"},{"a":2,"b":"y"}] | 两组两对象 |
| INSERT INTO t VALUES (1,'x'); | [{"col1":1,"col2":"x"}] | 省略列名 |
| INSERT INTO t (a) VALUES ('It''s ok'); | [{"a":"It's ok"}] | ''=字面单引号 |
| INSERT INTO t (a) VALUES ('x\ny'); | [{"a":"x\ny"}] | 反斜杠n |
| INSERT INTO t (a) VALUES ('a, b'); | [{"a":"a, b"}] | 串内逗号不拆 |
| INSERT INTO t (a) VALUES ('a)b'); | [{"a":"a)b"}] | 串内右括号 |
| INSERT INTO t (a) VALUES (NOW()); | [{"a":"NOW()"}] | 函数保原文 |
| INSERT INTO t (a,b) VALUES (NULL,TRUE); | [{"a":null,"b":true}] | NULL/TRUE |
| INSERT INTO t (a) VALUES (FALSE); | [{"a":false}] | FALSE布尔 |
| INSERT INTO t (a) VALUES (-3.5); | [{"a":-3.5}] | 负数 |
| INSERT INTO t (a) VALUES (1e3); | [{"a":1000}] | 科学计数法 |
| INSERT INTO `tbl` (a) VALUES (1); | [{"a":1}] | 反引号表名 |
| INSERT INTO [tbl] (a) VALUES (1); | [{"a":1}] | 方括号表名 |
| INSERT INTO "tbl" (a) VALUES (1); | [{"a":1}] | 双引号表名 |
| INSERT INTO t (a) VALUES (1); -- 行尾注释 | [{"a":1}] | 行注释剥离 |
| /* 前注释 */ INSERT INTO t (a) VALUES (1); | [{"a":1}] | 块注释剥离 |
| INSERT INTO t (a) VALUES ('a--b'); | [{"a":"a--b"}] | 串内双横线非注释 |
| INSERT INTO t (a,b) VALUES (1); | 报错:第 1 条语句第 1 组有 1 个值,与 2 个列名不符。 | 列值数不符 |
| SELECT * FROM t; | 报错:第 1 条语句不是 INSERT INTO 开头 | 非 INSERT |
第二张表汇总类型推断规则。大小写不敏感:null、Null、NULL 等价,true 与 TRUE 等价。
| 值写法 | 推断类型 | 说明 |
|---|---|---|
| 1 / -3.5 / 1e3 | number | 匹配数字正则才转,其余按字符串 |
| 'x' | string | '' 与反斜杠转义在字符串内还原 |
| NULL | null | 大小写不敏感 |
| TRUE / FALSE | boolean | 大小写不敏感 |
| NOW() / UUID() | string(保留原文) | 摘要标注未求值,不计算结果 |
| DEFAULT 等裸词 | string | 不在上表之内的原样保留 |
结果边界与错误提示
- 源文本为空或只有注释时,提示「SQL 源文本里没有语句」,不会输出空数组;点「转为JSON」会自动填回示例。
- 语句不是 INSERT INTO 开头时,提示第几条语句并引出开头三十个字符,方便确认是不是粘进了 SELECT 或 UPDATE。
- 列名括号、值组括号没有闭合时,分别提示「列名括号没有闭合」与「第几组值的括号没有闭合」,并给出语句序号。
- 一组值的个数与列名个数不一致时,提示「第几条语句第几组有 N 个值,与 M 个列名不一致」,不自动补 null,避免把错位数据悄悄塞进错误的列。
- 单引号字符串没有闭合、收尾引号后还有内容、单个值为空,都会给出带语句序号、组号与值序号的定位。
- 值组之后还有内容(如 ON DUPLICATE KEY UPDATE)时提示不支持该子句,并引出多余内容的前三十个字符。
- 函数调用一律保留原文,摘要列出未求值函数清单与处数,不会假装算出一个值。
- 本页不连接数据库、不执行 SQL;输出 JSON 不带字节序标记,导出的对照表 CSV 才带 BOM。
常见问题
为什么不直接按逗号切分?
因为逗号可能出现在字符串里。VALUES ('a, b', 2) 按逗号切会把一个字符串切成两半,后面的值全部错位。SQL 的词法规定字符串以单引号界定,只有维护「是否在单引号内」的状态才能正确找到分隔逗号,这也是本页扫描器的核心。
'' 和 \' 哪个才对?
SQL 标准用两个连续单引号表示一个字面单引号,写 'It''s ok' 得到 It's ok。反斜杠转义不是标准做法,但 MySQL 默认支持,本页两种都认:\' 变单引号,\\ 变一个反斜杠,\n 与 \t 变真换行与制表符。
NOW() 为什么不求值?
因为求值需要数据库环境,浏览器里没有当前时间戳与会话上下文,硬算出来的值必然和真实库不一致。本页保留原文并在摘要里列出未求值函数,把「这里原本是个函数」明确暴露出来,由你决定是否在数据库端补上默认值。
列名省略时键叫什么?
默认取 col1、col2、col3,序号从 1 开始,可以在「省略列名时的键前缀」里改。列名省略的 INSERT 依赖表中列的实际顺序,换环境极易错位,转完后务必对照表结构确认一遍。
多条 INSERT 为什么默认分开输出?
因为不同语句可能写不同表、不同列,合并会让来源不可考。默认每条语句输出一个数组,摘要里列出涉及的所有表;需要摊平时可切到合并模式,所有行进入同一个数组,键不一致的对象也能共存。
字符串里的括号、逗号、井号会出问题吗?
都不会。逗号在字符串内不是分隔符,右括号在字符串内不会提前结束值组,井号在 SQL 里没有特殊含义。扫描器只在字符串外才处理这些符号,注释剥离也同样只在字符串外生效。
支持 INSERT ... SELECT 吗?
不支持。本页只解析 INSERT INTO 表 (列) VALUES (...), (...); 这一种形态,读到 VALUES 之外的结构会提示不支持。INSERT ... SELECT 的源是查询结果,要转 JSON 应先把查询结果导出成值列表。
导出的文件带 BOM 吗?
JSON 输出与复制都不带字节序标记,避免下游解析器把 BOM 当成语法错误;只有值形态对照表的 CSV 导出带 BOM,这是给 Excel 开门用的。两者取向刻意相反。
相关工具
- SQL格式化工具:把压缩的 SQL 整理成可读缩进。
- CSV转JSON转换器:把表格导出转成对象数组。
- YAML转JSON转换器:处理带缩进的配置格式。
- XML转JSON转换器:把标签树转成嵌套结构。
- JSON转CSV转换器:反向把对象数组摊成表格。