IDEAICU 聚焦 VPS 云服务器评测、AI 工具、自托管部署教程与独立开发实践。

IDEAICU

每周收到同一份 CSV:用 SQLite 避免台账重复导入

先把 CSV 放入临时表,再按稳定编号合并。示例区分新增、更新与缺失记录,保留前导零,并避免把 REPLACE 当成普通更新。

文章目录

每周把供应商发来的 CSV 追加到台账,过几周就会出现同一个设备多行。直接清空重导,又可能丢掉你自己补的备注。适合这种场景的做法是先暂存文件,按稳定编号合并,把外部字段与本地字段分开。

先确定用哪一列识别同一条记录

设备名称会改,所在部门会变,文件里的行号也会重排。示例使用 asset_id 作为唯一编号,保留文本类型以免丢掉前导零。若来源根本没有稳定编号,需要先约定识别规则,不能拿名称相似就自动合并。

创建一个新的演示库;正式操作前另存现有台账备份。以下 CSV 保存为 assets.csv:

asset_id,name,department
0001,投影仪,会议室
0002,相机,设计组

进入 sqlite3 demo-assets.db,在 SQLite 命令行中执行:

CREATE TABLE assets (
  asset_id TEXT PRIMARY KEY NOT NULL,
  name TEXT NOT NULL,
  department TEXT,
  local_note TEXT
);
CREATE TEMP TABLE incoming (
  asset_id TEXT,
  name TEXT,
  department TEXT
);

再用命令行的点命令导入。下面的写法需要支持 --skip 的 sqlite3 CLI:

.mode csv
.import --skip 1 assets.csv incoming

--skip 1 跳过表头。先建暂存表,再导入,能够明确列数与类型;不能把错列文件直接塞进正式表。

合并前先查异常

SELECT asset_id, COUNT(*)
FROM incoming GROUP BY asset_id HAVING COUNT(*) > 1;
SELECT * FROM incoming
WHERE asset_id IS NULL OR trim(asset_id) = ''
   OR name IS NULL OR trim(name) = '';

第一条找到同一批文件中的重复编号,第二条找必填空值。出现异常时先处理文件,不要让“最后一行覆盖前一行”变成未经约定的规则。也要核对导入行数和几个原始编号。

只更新外部负责的字段

SQLite 3.24.0 起支持 UPSERT。异常处理完成后:

BEGIN;
INSERT INTO assets (asset_id, name, department)
SELECT asset_id, name, department
FROM incoming WHERE true
ON CONFLICT(asset_id) DO UPDATE SET
  name = excluded.name,
  department = excluded.department;
COMMIT;

WHERE true 用于消除这类 INSERT ... SELECT ... ON CONFLICT 的解析歧义。冲突时更新名称和部门,没有写入 local_note,本地备注就不会被这份外部 CSV 覆盖。INSERT OR REPLACE 可能删除冲突行再插入,涉及关联或触发器时与普通更新不同,不要混用。

来源文件里缺少某个编号,并不自动表示设备已经报废;它可能只是导出了某个部门。示例不会删除这些记录。只有明确约定“全量清单”及缺失处理方式后,才另做停用或删除流程。

把导入日期、文件名、行数和异常处理记在旁边。下一次更新前清空或重建暂存表,避免把两批输入混在一起。点命令详见 SQLite CLI 文档,合并行为见 UPSERT 说明。

继续阅读 · 工程实践 返回顶部