CSV 转 SQL
把表格数据变成能直接执行的建表语句和 INSERT,列类型按整列的值推断。
为什么类型要按整列判断
只看单个值很容易把一列「看起来是数字」的东西定成数值,结果中间夹了一个 N/A 就整批插入失败。这里的规则是整列统一:所有值都是整数才给 INTEGER,出现小数就升到 DECIMAL(18, 6),出现任何非数字就退回 VARCHAR / TEXT。宁可类型宽一点,也不要让数据在半路丢掉。
有几个看起来像数字、但必须当文本的情况:前导零(001、0571)、超过 15 位的编号、带区号括号的电话。数值类型会把前导零吃掉,长整数还会超出精确范围,所以这些一律按文本处理。日期只认 YYYY-MM-DD,时间只认 HH:MM[:SS],整列都符合才写 DATE / TIME,否则留作文本。
三种数据库的差异
主要差在引号和类型名。MySQL 用反引号包标识符,布尔是 TINYINT(1),日期时间是 DATETIME;PostgreSQL 用双引号,布尔是原生 boolean,日期时间是 timestamp,小数是 numeric;SQLite 用双引号,类型是动态的,这里统一给 TEXT / INTEGER / REAL 这几种亲缘类型。字符串里的单引号统一写成两个单引号,这是标准 SQL 的转义方式;MySQL 额外转义了反斜杠,避免 \' 被当成转义序列。
执行前先看一眼
生成的语句不包含主键、索引、NOT NULL 和默认值——这些是业务约束,样本推不出来。建议先导入测试库核对列类型,尤其是「看起来像数字的编号」和「空值是否允许」这两类。另外多值 INSERT 的批量条数不要设太大,超过 MySQL 的 max_allowed_packet 会直接报错。要把 CSV 先转成 JSON 看结构,用CSV 与 JSON 互转;想按列拆分或合并,用CSV 列拆分与合并。
常见问题
列类型是怎么推断的?
按整列的值统一判断:全是整数写 INTEGER/BIGINT,出现小数写 DECIMAL/NUMERIC,全是 true/false 写布尔,整列都是日期、时间或日期时间就写对应类型,其余一律写 VARCHAR 或 TEXT。只要有一个值不符合,就不会往窄类型上靠,宁可放宽也不让插入中途失败。
为什么 001、0571 这类编号被当成文本?
这是刻意的。前导零在数值类型里会被吃掉(001 变成 1),电话号码、邮编、订单号就毁了;超过 15 位的数字还可能超出精确整数范围。所以这类列统一按文本处理,插入时保留原样。
生成的语句能直接执行吗?
把输出全选复制到数据库客户端里就能执行。建议先开一个测试库跑一遍,确认列类型和空值处理符合预期再上生产。工具不猜主键、NOT NULL 和默认值——样本里没有空值不代表业务上不允许空值,这些约束需要你手动补。
多值 INSERT 和一行一条有什么区别?
多值写法把几十行合成一句 INSERT,执行时一次往返就写入一批,速度比一行一条快一个数量级。但单条语句过长会受 max_allowed_packet(MySQL)或内存限制影响,所以这里按「每条语句最多几行」分批,默认 100 行一批。
空单元格写 NULL 还是空字符串?
默认写 NULL,能区分「没有这个值」和「值就是空串」。如果目标列是 NOT NULL 且没有默认值,NULL 会导致插入失败,这时可以改成空字符串。注意 CSV 里的空字段和带引号的空字段("")在解析后都是空串,本工具不做区分。
表名或列名里有中文、空格会怎样?
中文会保留,空格和标点会被替换成下划线并加上标识符引号,页面会在提示里列出改写了哪些名字。名字以数字开头时前面会补一个下划线。这样生成的语句在三种数据库里都能执行,但也建议改完确认一下是否符合团队的命名规范。