为什么 SQLite 的 .mode insert 配合 .read 没有向目标表插入数据?
结论
.mode insert TargetTable 只改变查询结果的输出格式,把每一行显示为一条 INSERT INTO TargetTable ... 语句,生成的语句不会被执行。
.read Query.sql 会执行文件中的 SQL。文件里只有 SELECT,因此实际执行的是对 TbFiles 的查询,结果随后被格式化输出,TargetTable 不会发生变化。
示例中的两张表位于同一数据库,可以直接使用 INSERT INTO ... SELECT ...。
直接将查询结果写入目标表
连接 TEST.SQLITE 后执行:
INSERT INTO TargetTable (FileName, FileSize)
SELECT FileName, FileSize
FROM TbFiles;
这条 SQL 会直接写入数据,无需先生成 INSERT 文本或经过 CSV 文件。
显式列出字段,可以明确源字段与目标字段的对应关系,避免依赖 SELECT * 的列顺序。
如果希望继续通过 .read 完成操作,可以将 Query.sql 改为上述语句,再执行:
.read Query.sql
SQL 文件中的完整语句应以分号结束。
如果需要保留生成的 INSERT 脚本
也可以先将查询结果保存为 SQL 文件,再执行该文件。此时 Query.sql 保持为查询语句:
SELECT * FROM TbFiles;
在 sqlite3 命令行中依次执行:
.output target-inserts.sql
.mode insert TargetTable
.read Query.sql
.output stdout
.mode list
.read target-inserts.sql
第一次 .read 执行查询,并将生成的 INSERT 语句写入 target-inserts.sql;第二次 .read 执行这些语句,将数据写入目标表。这里假设当前目录中的 target-inserts.sql 可以被覆盖。
注意唯一约束和输出设置
TargetTable.FileName 定义了 UNIQUE 约束。如果目标表中已有相同的 FileName,再次插入可能因违反该约束而失败。应根据业务要求决定跳过重复记录还是更新已有记录;直接使用 INSERT INTO ... SELECT ... 不会自动处理这类冲突。
.separator , 控制相关输出格式使用的分隔符,不会执行插入。.output csv 中的 csv 是输出文件名;需要 CSV 格式时,应使用 .mode csv 设置格式,再用 .output 文件名 指定文件。
可以执行以下查询检查目标表内容:
SELECT FileName, FileSize
FROM TargetTable;
备注:内容仅供参考。
