Python使用mysql.connector导入CSV到MySQL出现SQL参数不足错误如何解决
错误根因
两类报错由同一个矛盾触发:
- 你创建的
v1表共有27列:26个自定义varchar字段 + 1个自增主键log_id - 导入的CSV仅包含26列业务数据,
tuple(row)生成的参数长度固定为26 - 未指定插入列的INSERT语句默认要求传入表全部列的值,自增列也不例外,因此会出现参数数量匹配冲突:
- 写≥27个%s:参数仅26个,触发
ProgrammingError: Not enough parameters for the SQL statement - 写≤26个%s:MySQL认为你需要传入27个值,触发
DataError: Column count doesn't match value count at row 1
- 写≥27个%s:参数仅26个,触发
修复方案
方案1:显式指定插入列(推荐,兼容性最高)
INSERT语句中明确写出要插入的26个业务列名,自增主键不需要传值,MySQL会自动生成:
for i,row in csv_data.iterrows(): sql = "INSERT INTO dv.v1 (c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18,c19,c20,c21,c22,c23,c24,c25,c26) VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" cursor.execute(sql, tuple(row)) # 操作完成后必须提交事务 db.commit()
方案2:给自增列传NULL占位
如果不想写全列名,可以给自增主键的位置传None作为占位符,MySQL会自动生成自增值:
for i,row in csv_data.iterrows(): # 拼接None对应log_id自增列 params = tuple(row) + (None,) sql = "INSERT INTO dv.v1 VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" cursor.execute(sql, params) db.commit()
额外优化建议
如果CSV数据量较大,逐行插入性能较差,可以用批量插入接口大幅提升效率:
# 批量生成参数列表 params = [tuple(row) for _, row in csv_data.iterrows()] sql = "INSERT INTO dv.v1 (c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18,c19,c20,c21,c22,c23,c24,c25,c26) VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" cursor.executemany(sql, params) db.commit()
如果后续需要把dd/mm/yyyy hh:mm:ss格式的时间字段存储为MySQL datetime类型,插入前可通过pd.to_datetime(对应字段值, format='%d/%m/%Y %H:%M:%S')做格式转换后再传入即可。
内容的提问来源于stack exchange,提问作者Zoltan Torok
相关产品推荐
相关产品推荐

