bash - 如何使用 CSV 文件更新表格中的所有列值?

标签 bash csv sqlite

我希望使用我导入并命名为表 songsnew 的 CSV 文件替换名为 songs 的 sqlite3 (Clementine) 数据库表中的列值。

CSV 文件包含三列标题,这些标题的字段名与目标数据库中的字段名相匹配。我希望它“索引”到的公共(public)列是 filename

使用 SQLiteBrowser,我尝试了从另一个答案中获取的 SQL:

update songs
set lastplayed = (select songsnew.lastplayed
where songsnew.filename = songs.filename)
where
exists (
select *
from songsnew
where songsnew.filename = songs.filename
)

它没有用。错误消息说:

no such column: songsnew.lastplayed: update songs

...这很奇怪,因为当我在 SQLite 数据库浏览器中输入该 SQL 时,它正确地“弹出”songsnew 表的 filename 列.

使用 SQLite3 和/或 bash,仅通过将 CSV 作为表格导入就可以做到这一点吗?哪种方式最简单,它是如何完成的?我不希望一次手动更新数千条记录。

按照评论中的要求,这里首先是架构歌曲:

CREATE TABLE `songs` (
    `title` TEXT,
    `album` TEXT,
    `artist`    TEXT,
    `albumartist`   TEXT,
    `composer`  TEXT,
    `track` INTEGER,
    `disc`  INTEGER,
    `bpm`   REAL,
    `year`  INTEGER,
    `genre` TEXT,
    `comment`   TEXT,
    `compilation`   INTEGER,
    `length`    INTEGER,
    `bitrate`   INTEGER,
    `samplerate`    INTEGER,
    `directory` INTEGER NOT NULL,
    `filename`  TEXT NOT NULL,
    `mtime` INTEGER NOT NULL,
    `ctime` INTEGER NOT NULL,
    `filesize`  INTEGER NOT NULL,
    `sampler`   INTEGER NOT NULL DEFAULT '0',
    `art_automatic` TEXT,
    `art_manual`    TEXT,
    `filetype`  INTEGER NOT NULL DEFAULT '0',
    `playcount` INTEGER NOT NULL DEFAULT '0',
    `lastplayed`    INTEGER,
    `rating`    INTEGER,
    `forced_compilation_on` INTEGER NOT NULL DEFAULT '0',
    `forced_compilation_off`    INTEGER NOT NULL DEFAULT '0',
    `effective_compilation` TEXT NOT NULL DEFAULT '0',
    `skipcount` INTEGER NOT NULL DEFAULT '0',
    `score` INTEGER NOT NULL DEFAULT '0',
    `beginning` INTEGER NOT NULL DEFAULT '0',
    `cue_path`  TEXT,
    `unavailable`   INTEGER DEFAULT '0',
    `effective_albumartist` TEXT,
    `etag`  TEXT,
    `performer` TEXT,
    `grouping`  TEXT
);

...这是导入后的 CSV 文件 songsnew 的架构:

CREATE TABLE `songsnew` (
    `filename`  TEXT,
    `playcount` TEXT,
    `lastplayed`    TEXT
);

最佳答案

这里有一个更方便的方法:

with delta(fn, pc, lp) as
(select a.filename, a.playcount, a.lastplayed from songsnew a )
update songs set 
     lastplayed = ifnull((select lp from delta where fn = filename), lastplayed),
     playcount  = ifnull((select pc from delta where fn = filename), playcount)
where filename in ( select fn from delta);

它使用

  • 用于解决歧义的 CTE,
    delta(fn, pc, lp) 作为 ...
  • 用于填充您在 songsnew 中可能没有的值的构造,
    ifnull(...)
  • 加速的where子句,
    (ifnull 构造也会阻止其他地方的更改,但要慢得多)

您可能希望通过 songsnew.playcount 增加 songs.playcount,在这种情况下使用 playcount = ifnull((select playcount+pc from delta where fn = filename), playcount)

关于 SQLite 3.18.0 2017-03-28

关于bash - 如何使用 CSV 文件更新表格中的所有列值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40711309/

相关文章:

javascript - 如何使用 Javascript 或 Java 获取 CSV 动态更改的实际数字

c++ - 如何在 Microsoft Visual C++ 2010 Express 项目中创建本地数据库?

bash - SQLite用新行导入字段

python - 无法执行 '.read create.sql'

mysql - 在 bash 脚本中使用带有 where 选项和长参数列表的 mysqldump

linux - 在 *.gz 文件上静默 zgrep 结果

python - 如何找到未列出或丢失的号码?

用于清理 Linux 服务器 session 文件夹的 Bash 脚本

c++ - 将 qresource QFile 与 FILE 一起使用

python - 需要将数据从文本文件提取到电子表格中进行分析