如何用CSV正确更新SQLite数据库中匹配的现有行?
如何用CSV数据正确更新SQLite中匹配的行(保留原有ID和行位置)
我看到你遇到的问题了——你的UPDATE语句没有指定匹配条件,导致每一次执行都把整个表的所有行都更新了,最后就全部变成CSV的最后一条数据了。咱们来一步步解决这个问题:
问题根源
你当前的executemany里的SQL语句缺少WHERE子句,所以每循环处理CSV里的一行数据,就会把itpassed_host表中的所有行都更新成这一行的值。当循环到CSV的最后一行时,所有自然就都变成最后那条数据了。另外,你的代码里读取CSV字段的键名和实际CSV的列名不匹配(CSV里是cfthostname,你代码里用的是hostname),这会导致读取不到正确的数据,甚至报错。
解决方案
我们需要用一个唯一标识来匹配数据库行和CSV行,从你给出的数据来看,cfthostname是每行唯一的,所以用它作为匹配条件最合适。同时,根据你的需求,优先只更新cert_time列(更高效,也符合你的核心需求),如果确实需要更新整行,也可以调整语句,但必须加上WHERE条件。
方案1:仅更新cert_time列(推荐)
这个方案完全贴合你的需求,只更新目标列,不改动其他数据:
import sqlite3 import csv conn = sqlite3.connect("C:\\db.sqlite3") cursor = conn.cursor() with open('C:\\csv\\update.csv','rt') as fin: dr = csv.DictReader(fin) # 匹配CSV列名,仅取更新需要的字段:cert_time和匹配用的cfthostname to_db = [(i['cert_time'], i['cfthostname']) for i in dr] # 使用WHERE子句,仅更新cfthostname匹配的行的cert_time cursor.executemany(""" UPDATE itpassed_host SET cert_time = ? WHERE cfthostname = ? """, to_db) conn.commit() conn.close()
方案2:更新整行(如果必须的话)
如果你确实需要更新整行(但保留行位置和原有ID),同样要加上WHERE条件确保只更新匹配的行:
import sqlite3 import csv conn = sqlite3.connect("C:\\db.sqlite3") cursor = conn.cursor() with open('C:\\csv\\update.csv','rt') as fin: dr = csv.DictReader(fin) # 匹配CSV列名,取所有字段,最后加上cfthostname作为匹配条件 to_db = [(i['cfthostname'], i['cftshortname'], i['cftenv'], i['cert_time'], i['cfthostname']) for i in dr] # 更新整行,但仅针对cfthostname匹配的行 cursor.executemany(""" UPDATE itpassed_host SET cfthostname = ?, cftshortname = ?, cftenv = ?, cert_time = ? WHERE cfthostname = ? """, to_db) conn.commit() conn.close()
关键说明
WHERE cfthostname = ?是核心:它确保每次只更新数据库中cfthostname和当前CSV行一致的那一行,而不是全表更新。- 修正了CSV字段读取的键名:比如
i['cfthostname']而不是i['hostname'],确保能正确读取CSV中的数据。 - 方案1更符合你的需求(仅更新cert_time),执行效率更高,也避免了不必要的字段更新。
执行后,你数据库中只有CSV里存在的cfthostname对应的行会被更新,其他行的原有数据(包括ID、行位置)都会保留,完全符合你的要求。
内容的提问来源于stack exchange,提问作者gipcu
相关产品推荐
相关产品推荐

