对照CS50教程用Python sqlite3插入CSV数据时遇绑定错误与单字符插入问题
错误根因
executemany()入参格式不匹配:该方法要求接收嵌套可迭代对象,每个子元素对应单行插入的绑定参数(单条参数需封装为元组/列表)。直接传入单个字符串title时,字符串会被迭代拆分为单个字符序列,最终逐字符插入。execute()入参格式不匹配:单条插入时,即使只有1个绑定参数,也必须封装为元组/列表格式。直接传入字符串会被Python迭代拆分为单个字符,触发“绑定参数数量不符”的报错。- 表结构逻辑:
shows表的id为INTEGER PRIMARY KEY,sqlite会自动为该列生成递增唯一值,插入时无需手动赋值,可保留现有结构,也可显式补充AUTOINCREMENT标记自增逻辑。
修正方案
方式1:循环内单条插入(易理解,适合小数据集)
直接在每次循环时,将title封装为单元素元组传入execute():
# PROGRAM TO AUTOMATICALLY INSERT TV SHOWS title INTO shows TABLE FROM CSV FILE IN PYTHON import sqlite3 import csv con = sqlite3.connect('shows.db') cur = con.cursor() # 避免重复建表报错,可根据需要删除该句 cur.execute("DROP TABLE IF EXISTS shows") # 建表,INTEGER主键会自动生成自增id cur.execute("CREATE TABLE shows (id INTEGER, title TEXT, PRIMARY KEY(id))") # Open CSV file with open("favorite_tv_shows.csv", "r", encoding="utf-8") as file: reader = csv.DictReader(file) for row in reader: # Canoncalize title title = row["title"].strip().upper() # 单参数必须封装为元组,*末尾的逗号不能省略*,否则会被识别为普通字符串 cur.execute("INSERT INTO shows (title) VALUES(?)", (title,)) con.commit() con.close()
方式2:批量插入(效率更高,适合大CSV文件)
先遍历CSV收集所有处理后的标题,再一次性调用executemany()批量插入:
import sqlite3 import csv con = sqlite3.connect('shows.db') cur = con.cursor() cur.execute("DROP TABLE IF EXISTS shows") cur.execute("CREATE TABLE shows (id INTEGER, title TEXT, PRIMARY KEY(id))") titles = [] with open("favorite_tv_shows.csv", "r", encoding="utf-8") as file: reader = csv.DictReader(file) for row in reader: title = row["title"].strip().upper() # 每个元素为单参数元组,符合executemany的入参要求 titles.append((title,)) # 批量插入所有收集到的标题 cur.executemany("INSERT INTO shows (title) VALUES(?)", titles) con.commit() con.close()
额外注意点
- 打开CSV文件时建议指定
encoding="utf-8",避免跨系统打开文件时出现中文乱码。 - 原代码中
id = cur.executemany(...)的赋值无意义,两个方法都不会返回插入的自增id,如需获取插入后的id可调用cur.lastrowid。 - 调试时可临时打印绑定参数的类型与内容,确认格式符合sqlite3的入参要求。
内容的提问来源于stack exchange,提问作者Chris Faux
相关产品推荐
相关产品推荐

