ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Excel公式拼SQL实战:自动生成INSERT/UPDATE/DELETE脚本的完整指南

2026/9/17 12:13:24 拓冰建站 浏览量
Excel公式拼SQL实战:自动生成INSERT/UPDATE/DELETE脚本的完整指南 上周有个同事抱着电脑过来说手里有张两千多行的Excel要把里面的数据跟线上库里的记录做匹配更新手头只有SQL Server Management Studio一条条改肯定不现实。我说你把Excel打开我教你用公式把UPDATE拼出来三分钟搞定。这个场景太常见了开发、测试、DBA、数据运维几乎每个人都遇到过类似的情况。这不是什么高大上的自动化方案就是用Excel公式拼接SQL脚本生成INSERT、UPDATE、DELETE语句再复制到数据库客户端里执行。我在日常开发、数据订正、测试数据准备里用了很多年最舒服的一点是整个过程透明可控脚本可以交给DBA审数据不用经过额外工具。下面就从使用场景、三类SQL的生成方式、内容清洗的坑一直聊到批量提交和数据量边界都是实操里走出来的经验。1. 为什么我坚持用Excel公式拼SQL而不是导入工具1.1 这个方案最适配的场景如果只看标题可能会觉得这方法很土但实际工作中它非常能打。我总结下来这样几个场景尤其适合Excel本身就是数据源头多张表关联整理好的结果就在里面数据量在几百到几万行之间没到必须上ETL工具的程度手头只有数据库客户端没有Navicat、DBeaver或者导入向导因为权限被禁用需要把脚本提交给DBA执行不能自己直连生产库插入或更新前要做字段映射、条件判断、格式转换。这些场景里用Excel公式生成SQL比在Navicat里走导入向导更直观。尤其最后一条当Excel里有两列需要合并成一个字段或者空值要转成NULL导入向导的映射反而绕来绕去公式一行就写清楚了。另一个容易被忽略的优点是可审阅。脚本生成后能看到每条语句的完整样子哪条数据要改成什么白纸黑字摆在Excel里DBA检查起来也放心。1.2 不选导入向导的原因以及什么时候必须换很多人会问数据库客户端不是自带导入CSV、Excel的功能吗为什么还要拼SQL。以我的经验导入向导在数据规整、表结构简单、可直连数据库时确实方便。但有几种情况会卡住公司网络策略禁止直连生产库只给你一个查询或回写工单入口Excel里的数据不是一份干净的CSV中间有合并单元格、标题行、备注列菜单里的导入向导经常被这类不规整格式坑字段写到数据库之前要做映射比如把Excel里的“在职/离职”翻译成1和0或者把带单位的价格字符串拆成数字导入向导执行完成后很难审计出了问题不知道这条数据是谁改的、怎么进来的。所以我一般这样判断数据量在1万行以内字段逻辑有加工要交付脚本走审批优先用Excel拼SQL数据量几十万行或者Excel本身只是中间态我更倾向直接写Python脚本或者用数据库原生的批量导入命令。拼SQL不是万能的但它适合它适合的场景核心诉求很简单把活干了还干得明白。2. 从Excel到INSERT语句公式怎么设计才能一次成型2.1 先理清表结构和Excel列对应关系动手之前先建一个映射关系表。比如要往users表插入数据表结构是CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(50), age INT, created_at DATETIME );Excel里的列需要和这四个字段一一对应。强烈建议把Excel第一行写成字段名跟数据库字段保持一致后期排查的时候少很多麻烦。我一般会在Excel里直接加一列名为SQL_Text的辅助列专门放拼接出来的SQL文本保持原始数据列不动这样出了问题还能对照原始值不用来回翻。2.2 基础INSERT拼接公式假设Excel行2的数据是A2idB2nameC2ageD2created_at日期格式。在E2输入INSERT INTO users (id, name, age, created_at) VALUES (A2, B2, C2, TEXT(D2,yyyy-mm-dd hh:mm:ss));回车后E2就会生成类似这样的内容INSERT INTO users (id, name, age, created_at) VALUES (1, 张三, 25, 2024-05-20 10:30:00);这个公式的核心是符号拼接。Excel公式里所有静态文本都放在双引号中单元格引用放在外面。注意name是varchar类型所以公式里在B2前后加了单引号C2是int类型就不加D2是日期必须用TEXT函数格式化否则拿到的会是Excel内部的日期序列号比如45292这种数字数据库直接报错。如果你第一次写这种公式建议先在空单元格试一行确认输出结构没问题再往下拖。2.3 日期、文本、数值在公式里的三种写法这里把三类常见字段的拼接规则单独说清楚照抄不会错字段类型Excel值示例公式写法输出结果数值100A2100文本张三B2张三日期2024/5/20TEXT(D2,yyyy-mm-dd hh:mm:ss)2024-05-20 10:30:00日期这块要特别提醒不同数据库的字符串日期规则有差异MySQL、SQLite、PostgreSQL一般直接识别2024-05-20 10:30:00SQL Server在大多数语言环境下也能识别但如果你遇到显式转换报错可以用CONVERT(datetime, 2024-05-20, 120)包一层Oracle就比较严格需要TO_DATE(2024-05-20 10:30:00, YYYY-MM-DD HH24:MI:SS)。遇到这种情况直接改Excel公式输出即可不需要动数据源。3. UPDATE和DELETE脚本批量改数时最容易翻车的地方3.1 WHERE条件是批量UPDATE的生命线生成UPDATE脚本公式和INSERT差别不大但危险程度翻倍。以更新用户年龄为例UPDATE users SET ageC2 WHERE idA2;输出UPDATE users SET age25 WHERE id1;看起来很简单但要注意几个点。第一WHERE条件里的id必须是唯一的如果Excel里有两行相同id最后一行的值会覆盖前面的导致结果和预期不符。第二如果还想更新多个字段用逗号分隔公式写成UPDATE users SET nameB2, ageC2 WHERE idA2;第三UPDATE前一定先核对。没有WHERE的UPDATE就是全表更新这在数据订正时是灾难。我在生成脚本前会用辅助列统计一下Excel里WHERE条件的值是否重复用COUNTIF扫一遍发现重复就先去重确保每条UPDATE都只影响期望的那一行。3.2 DELETE脚本的安全检查DELETE公式更短DELETE FROM users WHERE idA2;但越短越容易掉以轻心。我在给团队做分享时反复强调一个习惯DELETE生成后先不要直接执行把DELETE FROM替换成SELECT COUNT(*) FROM跑一遍验证一下影响行数确认就是你要删的那几条再放真正的删除脚本。如果需要根据多个条件删可以用AND连接。比如Excel中有部门和入职日期两列DELETE FROM users WHERE departmentB2 AND join_dateTEXT(C2,yyyy-mm-dd);这种SQL带上事务更稳妥。MySQL和SQL Server都可以在执行前先用BEGIN;或BEGIN TRANSACTION;删完查一遍再COMMIT;不对就ROLLBACK;。脚本是交给DBA执行的在SQL文件里保留事务段落也是专业性的体现。删数据这件事多一道验证就少一分事故。3.3 UPDATE时遇到NULL和空值的处理Excel里如果是空单元格直接拼接会得到类似SET age WHERE id1的残缺语句必然报错。更隐蔽的是如果某列允许NULL业务上希望把空的Excel值写成NULL公式要加判断UPDATE users SET ageIF(C2, NULL, C2) WHERE idA2;文本字段写法类似只是空值要决定是写成NULL还是空字符串UPDATE users SET nameIF(B2, NULL, B2) WHERE idA2;这里也埋了个坑Excel里的空格不等同于空很多从系统导出的Excel单元格看起来是空的其实有空格。所以做判断前最好先用TRIM清理写成IF(TRIM(B2), ...)否则你以为处理了实际还是拼出了带空格的值验证时就会对不上。4. 空值、单引号、换行、科学计数法拼SQL前先处理这四个大坑4.1 空值拼成NULL而不是NULL上面已经涉及一部分但值得单独拿出来。INSERT场景下空值处理同样关键。对于数值字段INSERT INTO users (id, name, age) VALUES (A2, B2, IF(C2, NULL, C2));对于文本字段如果业务上“空”就要存NULL则写成INSERT INTO users (id, name, age) VALUES (A2, IF(B2, NULL, B2), IF(C2, NULL, C2));注意这里的引号比较绕B2在公式中表示输出单引号包裹的内容。因为Excel字符串定界符是双引号所以单引号可以直接写。这个步骤容易错建议先在空表里试一行看看输出结果到底是NULL还是NULL后者会把字符串NULL写进数据库类型对不上时直接报错类型对上时也是一颗暗雷。4.2 字符串里的单引号要双写这是Excel拼SQL最经典的报错来源。如果Excel里有一个值是OBrien直接拼出来的SQL是OBrien数据库会认为字符串在O后面就结束了后面的Brien变成非法内容。ANSI SQL标准的处理方式是单引号转义为两个单引号所以在Excel公式里嵌套一个SUBSTITUTESUBSTITUTE(B2, , )在最终INSERT公式里就是INSERT INTO users (id, name) VALUES (A2, SUBSTITUTE(B2, , ));MySQL用户可能会习惯用\但为了脚本在不同数据库之间迁移方便我个人统一用双单引号PostgreSQL和SQL Server同样适用。这个处理不能省业务数据里带英文缩写、人名、产品描述时单引号出现的概率比你想的高得多。4.3 换行符和制表符会让整条SQL断掉Excel单元格里如果有AltEnter换行拼出来的SQL会把一个字符串字面量切成两行。某些客户端还能继续解析因为有引号包着但肉眼很容易看成两条SQL而且复制到审批系统或脚本文件时可能出现格式问题。更稳妥的做法是在拼接前把换行符替换成空格SUBSTITUTE(SUBSTITUTE(TRIM(B2), CHAR(10), ), CHAR(13), )CHAR(10)对应换行LFCHAR(13)对应回车CR。Windows系统从Excel复制出来的换行常常是CRLF两个字符都有所以两个SUBSTITUTE都要写只替换一个会出现行尾还残留半截的情况。如果你还遇到过制表符导致的对不齐可以在公式里继续套一层SUBSTITUTE把CHAR(9)也替换掉。内容清洗宁可做多不可做少。4.4 数字精度和科学计数法的干扰Excel超过11位的纯数字会自动显示成科学计数法而且位数超过15位时会丢失精度。身份证号、手机号、业务编号都是重灾区。如果Excel列还没有完全变成科学计数法马上把单元格格式改成“文本”重新录入如果已经变了数据精度已经丢了Excel本身救不回来只能回到原始系统重新导出。如果数字在有效范围内但单元格格式显示有问题可以在公式里加TEXTTEXT(A2, 0)比如A2是18位数字但被转成科学计数法用TEXT也救不回精度因为底层数值已经丢失。所以务必养成习惯从系统导出Excel时凡是不参与计算的“长数字”列提前设置成文本格式。公式层面能做的只是避免小数字被显示成科学计数法顺带让生成的SQL看起来干净。5. 公式看起来没问题SQL执行却报错一次完整排查过程5.1 报错发生在哪一行先定位再改之前帮同事处理过一个实际案例。她用Excel拼好了一批UPDATE脚本复制到SSMS执行报错信息是“-附近有语法错误”。她盯着公式看了半天没发现问题。我让她把报错指向的那条SQL单独复制出来先放到一个空白SQL窗口里执行还是同样的错误。然后把这条SQL原样贴到Notepad里打开“显示所有字符”一眼就看到日期字段的值是2024-1-1 10:00:00而她在Excel里看到的是2024-01-01。为什么因为日期列在Excel里被当成了文本源数据里就带了一个手动录错的短格式。数据库客户端在解析这个没有前导零的日期时在减号附近报错了。5.2 把生成的SQL当成纯文本检查这个案例的关键在于不能只盯公式要盯公式的输出。方法很简单在Excel里点中公式单元格按F2进入编辑态全选公式内容看一遍或者把生成的那一列复制到记事本里用“显示所有字符”看不可见字符。很多隐蔽问题都是这样浮出来的字符串两边多了空格变成 张三 查询匹配不上看不见的换行符SQL被硬拆成两行肉眼误以为语句结束全角逗号或全角括号从某些网页、微信复制下来的内容里夹杂全角符号SQL语法直接崩。排查顺序我一般固定为先看报错行附近再用编辑器看特殊字符最后回头检查Excel原始列。别一上来就怀疑公式拼接逻辑公式错通常会错得很有规律比如整列都是同一个位置错反而是源数据里的脏值才会在这个单元格错、那个单元格不错。5.3 字段类型和数据库方言的坑还有一种报错不是引用和符号问题而是类型转换。同样是日期字符串2024-01-01 10:00:00MySQL可以直接用在datetime字段的插入里SQL Server在某些语言环境下也能识别但如果你在SQL Server里遇到类似“从字符串转换日期和/或时间失败”的报错通常就是当前会话的日期格式和字符串不匹配。解决方式是在Excel公式里直接输出CONVERT包裹的形式INSERT INTO users (id, created_at) VALUES (A2, CONVERT(datetime, TEXT(D2,yyyy-mm-dd hh:mm:ss), 120));Oracle同理改成TO_DATE(..., YYYY-MM-DD HH24:MI:SS)。遇到这种问题别在Excel里纠结先确认目标数据库方言再改公式输出结构。同样值得注意的还有保留字问题比如字段名刚好叫order或descMySQL要加反引号SQL Server要加方括号这些细节在生成脚本前就应该确认好而不是等报错再去翻每一条SQL。6. 批量提交优化多值INSERT与分批执行怎么落地6.1 多值INSERT怎么用Excel拼出来一次生成一条INSERT执行一万条就是一万次网络往返虽然数据量不大时客户端能扛住但效率很低。更常见的做法是拼多值INSERT。MySQL、PostgreSQL、SQL Server都支持一条INSERT插入多行比如INSERT INTO users (id, name, age) VALUES (1, 张三, 25), (2, 李四, 30), (3, 王五, 28);用Excel生成时辅助列公式可以这样写每行生成一个带逗号结尾的括号组(A2, B2, C2),然后把这些行复制到文本编辑器把最后一行的逗号改成封号并在最前面加上INSERT INTO users (id, name, age) VALUES和换行。如果嫌手动处理麻烦还可以反过来先把所有括号组生成好编辑器里统一用字符串查找替换把最后一行的规律找出来再改。实际操作中复制到编辑器处理最顺手不要在Excel里硬拗一个判断最后一行的复杂公式容易把自己绕晕。6.2 分批执行和事务处理多值INSERT不是无限制的。MySQL有max_allowed_packet限制单条SQL太大一样会被拒绝SQL Server单条批处理过大也可能超时。我习惯的做法是每500行一组生成多值INSERT一组一组复制执行。分组时注意每条INSERT内行数保持一致方便估算影响行数。更稳妥的交付方式是整包脚本外面套事务BEGIN; -- 这里放所有INSERT/UPDATE/DELETE脚本 COMMIT;执行时先让DBA在测试库或事务里跑一遍确认影响行数和预期一致再提交。数据订正这种事多花一分钟验证能省一天回滚的时间。还有一个小细节生成脚本时最好在文件里注释上生成时间、Excel版本、对应业务单号这样后续DBA审阅时能快速定位来源也方便归档追溯。6.3 数据量到多大就应该换工具Excel公式拼接SQL不是没有边界。以我实际经验单次生成超过2万条SQL后Excel文件本身还是顺畅但脚本文件体积变大复制粘贴到数据库客户端、审批系统、工单系统都有可能卡顿。接近10万条时手动复制已经不可靠很容易漏行。这时候我有两个替代思路第一用Excel公式生成好部分列再用Python脚本批量组装成SQL文件第二直接用pandas读取Excel调用to_sql或者自己循环拼SQL落地成SQL文件交给DBA。不需要把工具用到底Excel负责它的强项——结构化整理和公式可视化批量拼装交给代码是更合理的分工。这不是否定Excel而是明确它的适用边界。7. 用Excel拼SQL的适用边界以及我最后想提醒你的几件事7.1 我在实际使用中总结的几条操作习惯用这套方法五六年我攒了几个看起来很小但很实用的习惯。第一Excel里永远保留原始数据列只新增辅助列不要把数据先改一遍再拼SQL这样出了问题还能回溯到最源头。第二每一批脚本生成后先提取第一条和最后一条看一眼确认首尾都是完整SQL没有半截内容。第三脚本里的表名和字段名一定先从数据库里查出来复制不要手敲尤其是下划线命名和大小写不敏感的字段手敲容易错。另外脚本交付前建议用编辑器统一检查一遍。我会把所有SQL粘贴到Notepad启用“显示所有字符”重点检查有没有NULL被拼成NULL、有没有多余的逗号、有没有把WHERE漏掉。看起来麻烦实际上做多了一分钟就能扫完几千行。这种事前检查比事后回滚便宜太多。7.2 这个方法的边界什么时候别再坚持用Excel如果数据来自Excel但需要对数据库现有数据和Excel做关联或者数据量已经到几十万行或者更新逻辑复杂到要按条件分支我不会坚持在Excel里拼SQL。那是Python和数据库原生批量工具的战场。Excel拼SQL适合的是“数据已经整理好、结构相对固定、需要快速生成可审阅脚本”的场景它最大的价值不是效率多高而是透明、可控、没有黑盒。数据库之间还有一些细节差异比如自增主键的插入是否需要显式指定ID、字符串字符集和排序规则、保留字要不要加反引号或方括号这些都需要在生成脚本前确认。但只要公式结构干净字段类型处理正确这套方法在MySQL、SQL Server、PostgreSQL、SQLite上都能跑通。最后再分享一个小经验拿到Excel的第一件事先看表头再看行数最后随便取一行数据试生成一条SQL执行成功后再批量生成。很多问题在第一条SQL执行时就能暴露等你拖完上万行再去执行定位成本就高了。愿这条土办法也能帮你少加几次班。