CSV 按主键比较
数据互转
正在载入
正在加载工具
工具代码会在打开时按需载入,请稍候。
本工具的全部运算都发生在你的浏览器中,输入内容不会发送到任何服务器。
关于这个工具
按能标识记录的列比较两份 CSV 快照,而不是逐行对齐文本。粘贴内容或选择本地文件,再指定双方共有的一个主键列,或多个列组成的复合主键。报告分别统计新增、删除、变化和未变化的行,列出新增与删除的列,并展示单元格前后值。适合订单导出和仓库库存快照等场景:只改变排序,不应被当成大量记录修改。解析与比较在可终止的浏览器工作线程中本地运行;本工具不上传或持久保存输入。
常见用途
- 按 order_id 核对前后两份订单导出,查找新订单、删除记录和状态或金额文本的变化。
- 按 warehouse 与 sku 组成的复合主键比较库存,让不同仓库中的同一商品保持为独立记录。
- 区分 CSV 列结构变化与行内容变化,再保存保留原始字符串的 JSON 报告或长格式差异 CSV。
使用方法
- 1.粘贴比较前、比较后的 CSV,或分别选择本地文件。每边独立选择逗号、分号、制表符或竖线分隔符,并确认首行是否为表头。按需选择文件编码;支持 UTF-8、UTF-16LE 和 UTF-16BE。 先运行列检查,再查看可用列,选择两边均存在且名称完全一致的一个或多个主键列。关闭表头时使用自动生成的 column1、column2 等列名。复合主键把所选值组合使用,每个完整组合在每边至多对应一行。
- 2.默认保持字符串精确比较;仅在确有需要时启用去除首尾空白或忽略大小写。这两项同时影响主键匹配和单元格相等判定,不改变表头。默认拒绝任一主键分量为空;仅在空值有明确含义且仍能唯一标识记录时主动允许。 运行比较,检查行统计、新增与删除列,以及单元格差异。先修复重复主键或解析诊断,再重试;存在歧义时不会生成部分匹配。需要时可取消任务。修改输入或比较设置会使旧结果失效。
- 3.下载 JSON 报告以保留原始单元格字符串,或导出含 kind,key,column,before,after,before_present,after_present 列的差异 CSV。key 字段为 JSON 数组。用于电子表格时保留公式防护;只有确认警告及目标软件行为后才选择原始导出。 屏幕筛选和缩略预览不会删减导出数据。
可复现的主键比较示例
订单状态变化与行顺序调整
{
"before": "order_id,status,total\n001,pending,12.50\n002,paid,0\n003,paid,7",
"after": "order_id,status,total\n003,paid,7\n001,paid,12.50\n004,pending,5",
"beforeOptions": {
"delimiter": ",",
"header": true
},
"afterOptions": {
"delimiter": ",",
"header": true
},
"compareOptions": {
"keys": [
"order_id"
],
"trim": false,
"ignoreCase": false,
"emptyKeys": "reject"
}
}{
"summary": {
"added": 1,
"removed": 1,
"changed": 1,
"unchanged": 1,
"cellsChanged": 1
},
"columnsAdded": [],
"columnsRemoved": []
}选择 order_id 作为主键。订单 004 新增、002 删除、001 的状态改变,003 未变化。调整行顺序不会产生额外差异;示例输出为简要统计。
仓库与 SKU 组成的库存复合主键
{
"before": "warehouse,sku,qty,note\nNorth,A,10,\"ready, packed\"\nSouth,A,5,\"line 1\nline 2\"\nNorth,B,8,hold",
"after": "sku,warehouse,note,qty\nA,South,\"line 1\nline 2\",6\nA,North,\"ready, packed\",10\nC,North,new,4",
"beforeOptions": {
"delimiter": ",",
"header": true
},
"afterOptions": {
"delimiter": ",",
"header": true
},
"compareOptions": {
"keys": [
"warehouse",
"sku"
],
"trim": false,
"ignoreCase": false,
"emptyKeys": "reject"
}
}{
"summary": {
"added": 1,
"removed": 1,
"changed": 1,
"unchanged": 1,
"cellsChanged": 1
},
"columnsAdded": [],
"columnsRemoved": []
}同时选择 warehouse 和 sku。South/A 的数量从 5 变为 6,North/B 删除,North/C 新增,North/A 未变化。表头顺序调整不影响匹配;带引号的逗号和多行备注均作为单元格内容解析。
按精确表头名匹配调换的列
{
"before": "id,name\n1,Alice",
"after": "name,id\nAlice,1",
"beforeOptions": {
"delimiter": ",",
"header": true
},
"afterOptions": {
"delimiter": ",",
"header": true
},
"compareOptions": {
"keys": [
"id"
],
"trim": false,
"ignoreCase": false,
"emptyKeys": "reject"
}
}{
"summary": {
"added": 0,
"removed": 0,
"changed": 0,
"unchanged": 1,
"cellsChanged": 0
},
"columnsAdded": [],
"columnsRemoved": []
}name 和 id 的位置互换,但列名和值均未改变。启用表头时,该行仍为未变化。
保留前导零与小数字面写法
{
"before": "id,code,total\n001,007,1.0",
"after": "id,code,total\n001,7,1",
"beforeOptions": {
"delimiter": ",",
"header": true
},
"afterOptions": {
"delimiter": ",",
"header": true
},
"compareOptions": {
"keys": [
"id"
],
"trim": false,
"ignoreCase": false,
"emptyKeys": "reject"
}
}{
"summary": {
"added": 0,
"removed": 0,
"changed": 1,
"unchanged": 0,
"cellsChanged": 2
},
"columnsAdded": [],
"columnsRemoved": []
}所有值都按字符串处理。主键 001 的 code 从 007 变为 7,total 从 1.0 变为 1,因此该行有变化。工具不会将它们自动转为数字,也不会执行财务计算。
空单元格也保留列结构变化
{
"before": "id,old\n1,",
"after": "id,new\n1,",
"beforeOptions": {
"delimiter": ",",
"header": true
},
"afterOptions": {
"delimiter": ",",
"header": true
},
"compareOptions": {
"keys": [
"id"
],
"trim": false,
"ignoreCase": false,
"emptyKeys": "reject"
}
}{
"summary": {
"added": 0,
"removed": 0,
"changed": 1,
"unchanged": 0,
"cellsChanged": 2
},
"columnsAdded": [
"new"
],
"columnsRemoved": [
"old"
]
}old 列被删除,new 列被新增。不存在的列与存在但值为空字符串的列不同,因此匹配行仍标为变化。这是结构差异,不会猜测列重命名。
主动启用去除首尾空白与忽略大小写
{
"before": "id,status\n A , Paid ",
"after": "id,status\na,paid",
"beforeOptions": {
"delimiter": ",",
"header": true
},
"afterOptions": {
"delimiter": ",",
"header": true
},
"compareOptions": {
"keys": [
"id"
],
"trim": true,
"ignoreCase": true,
"emptyKeys": "reject"
}
}{
"summary": {
"added": 0,
"removed": 0,
"changed": 0,
"unchanged": 1,
"cellsChanged": 0
},
"columnsAdded": [],
"columnsRemoved": []
}同时启用两项后,主键与 status 均比较相等。JSON 报告仍保留原始大小写和首尾空白。这两项设置不改变表头匹配规则。
拒绝无法唯一匹配的重复主键
{
"before": "id,name\n1,Alice\n1,Bob",
"after": "id,name\n1,Alice",
"beforeOptions": {
"delimiter": ",",
"header": true
},
"afterOptions": {
"delimiter": ",",
"header": true
},
"compareOptions": {
"keys": [
"id"
],
"trim": false,
"ignoreCase": false,
"emptyKeys": "reject"
}
}{
"error": "duplicateKey",
"side": "before"
}比较前的两行都使用主键 1。工具会停止比较并给出重复主键诊断,不会任意选取 Alice、Bob 或第一行、最后一行。
用不同分隔符比较无表头文件
{
"before": "001;alpha\n002;beta",
"after": "001|alpha\n003|gamma",
"beforeOptions": {
"delimiter": ";",
"header": false
},
"afterOptions": {
"delimiter": "|",
"header": false
},
"compareOptions": {
"keys": [
"column1"
],
"trim": false,
"ignoreCase": false,
"emptyKeys": "reject"
}
}{
"summary": {
"added": 1,
"removed": 1,
"changed": 0,
"unchanged": 1,
"cellsChanged": 0
},
"columnsAdded": [],
"columnsRemoved": []
}比较前选择分号,比较后选择竖线,并为两边关闭表头。以自动生成的 column1 为主键,002 删除、003 新增,001 未变化。
常见比较误区
- 同一商品在不同仓库各有一行,却只选择 sku 作为主键。
- 分隔符或表头选项错误,仍从解析错误的列中选择主键。
- 忽略字符串比较规则,把 001 与 1、1.0 与 1 当成相同。
- 开启大小写或首尾空白规范化后,未检查原本不同的主键是否发生冲突。
- 把标识符变化理解为原行修改,或期待自动识别列重命名。
- 用电子表格打开不可信的原始差异 CSV,或分享前未检查导出内容中的私密信息。
限制与说明
- 每边文件字节与解码后文本的 UTF-8 字节均不得超过 2 MiB,另限 10,000 个数据行、128 列和 200,000 个单元格;单次导出上限为 12 MiB。工作线程设有时限并支持取消,超过限制会停止操作。更大的快照可按主键范围分片后成对比较,或使用本地数据库、数据处理工具。工作线程时限并非严格的内存沙箱。 文件必须能严格解码为 UTF-8、UTF-16LE 或 UTF-16BE。BOM 必须与所选编码一致,并在解析前移除。处理 BOM 不代表支持 GBK、Shift_JIS 等旧编码,请先重新导出为受支持编码。分隔符需明确选择;错误引号和行宽不一致会被拒绝,不会自动修补。 屏幕每页显示 25 行,每行最多展示 12 个单元格和 6 个主键分量,并缩略较长的值。完整内容请查看导出报告。
- 表头按名称精确匹配,不受列顺序影响;空白或重复表头会被拒绝。忽略大小写或空白的选项不会规范化、重命名表头。无表头时,column1、column2 等名称代表位置,调换列顺序会改变其含义。 新增或删除列属于结构变化,因此匹配行即使相关单元格为空,也可能标为变化。不会推断列重命名;主键改变会表现为删除一行并新增一行。行顺序本身不参与比较。
- 任一边存在重复完整主键都会停止比较,包括去除首尾空白或忽略大小写产生的冲突。不会猜测取第一行、最后一行或多对多匹配。默认拒绝所选主键中任一分量为空;主动允许空值也不会关闭重复键检查。 所有单元格始终是字符串:001 不同于 1,1.0 不同于 1。去空白仅去除首尾空白;忽略大小写不提供模糊匹配、Unicode 规范化、语言区域排序或数值容差。不会计算日期、数字或公式。
- JSON 在启用相等判定选项后仍保留解析所得的原始字符串,但不是源文件的逐字节副本。差异 CSV 是长格式变化报告,不是合并后的表格或可直接导入的补丁。安全导出会在类似公式的字段前加单引号,因而改变其导出文本。原始导出可能触发表格公式;CSV 引号本身无法防护,各表格软件也可能以不同方式解释数据。 before_present 与 after_present 字段区分缺失单元格和空字符串。在表格软件中保存后重新打开,单引号防护可能被移除;不存在对所有软件都绝对安全的 CSV 导出。 差异 CSV 每个受影响单元格占一条记录,新增或删除行会包含其中每个现有单元格;未变化行仅保留在 JSON 中。JSON 用 null 表示缺失单元格,而文本 null 仍是字符串。 对于没有数据行的表,仅有列结构变化时,差异 CSV 不会产生单元格记录;请用 JSON 保留完整列元数据。
- 内容以文本显示,不运行 HTML、脚本或公式。输入与结果留在页面内存中,直到清空或关闭页面;本工具不添加上传或持久存储。下载的报告可能包含私密数据,离开页面后不受页面控制。
常见问题
怎样选择主键并处理重复主键错误?
选择两边共有、能唯一标识一条记录的列。订单可使用 order_id,分仓库存可组合 warehouse 与 sku。排序后临时生成的行号通常不适合作为主键,因为下次导出时可能对应另一条记录。 同一主键对应多行时,无法唯一确定配对关系。诊断会标明受影响的一边及从 1 开始的数据行号。解析错误使用包含表头的 CSV 记录号;带多行字段时,记录号可能不同于物理行号。补选缺失的主键列,或明确整理源数据的重复记录后重试。去除首尾空白和忽略大小写也可能让原本不同的键产生冲突。
两份文件可以使用不同分隔符、列顺序或编码吗?
可以,两边输入设置相互独立。例如可比较 UTF-8 逗号分隔文件与受支持的 UTF-16 制表符分隔文件。有表头时,即使列顺序不同,也按精确列名匹配;不会翻译、去除表头空白或推断改名。
忽略大小写或空白会修改原始数据吗?
只改变相等判定与主键匹配。JSON 的前后值仍保留解析所得原始字符串。这些选项也作用于主键单元格,请检查是否因此产生冲突。表头仍必须精确一致。
哪种导出能保留原始值与缺失单元格的区别?
需要保留原始字符串和结构区别时选择 JSON。差异 CSV 用长格式记录变化,主键以 JSON 数组表示。用于电子表格时请保留单引号公式防护。原始 CSV 保留单元格文本,但可能被解释为公式,仅适用于你已评估的目标系统。 空字符串是现有列中的一个值;缺失列是表结构差异。报告保留该区别,列出新增或删除列,并把匹配行中受影响的单元格记入变化,不会悄悄将两者视为相等。