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

问题描述:

我希望使用我导入的CSV文件替换名为songs的sqlite3(Clementine)数据库表中的列值,并将其命名为songsnew如何使用CSV文件更新表中的所有列值?

CSV文件有三列,其中的字段名称与目标数据库中的字段名称匹配。我希望它“索引”到的共同列是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 

...这是奇怪的,因为作为我打字是SQL到SQLite数据库浏览器,它可以正确标识为songsnew表“弹出”列filename

使用SQLite3和/或bash,只能通过将CSV作为表格导入来完成此操作吗?哪种方法最简单,它是如何完成的?我不想一次一个地手动更新数千条记录。

的要求,在评论,这里是第一架构songs

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 
); 
+0

你是如何获得数据到SQLiteBrowser的?如果你已经导入它,它已经在那里。在'sqlite3'命令行shell中显示'.schema'的输出。 –

+0

好的 - 上面已经添加了。 – user3447273

+0

列在那里。你把它导入到同一个数据库吗? –

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

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为各地歧义获得,
    with delta(fn, pc, lp) as ...
  • 一个结构来填充的值,你可能无法在songsnew有,
    ifnull(...)
  • 一个WHERE子句加快,
    (中ifnull构造也可以防止其他地方发生变化,但速度要慢得多)

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

在SQLite 3.18.0 2017-03-28