我希望使用我导入并命名为表 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/