
本文详解如何使用 python 的 mysql-connector 驱动安全、高效地将 csv 文件数据批量插入 mysql 数据库,重点解决因 sql 占位符误用、事务未提交、首行标题未跳过等导致的插入失败问题。
在 Python 中通过 CSV 文件向 MySQL 插入数据是常见需求,但初学者常因细节疏忽(如字符串格式化滥用、缺少事务提交、忽略 CSV 表头)而报错。你遇到的 mycursor.execute(..., row) 报错,根本原因在于:错误地在 SQL 语句中手动添加了单引号 ',同时又将参数以元组形式传入,导致 MySQL 驱动器无法正确解析参数类型,引发语法或类型不匹配错误。
✅ 正确做法是:使用 %s 占位符(无引号),由驱动器自动处理类型转换与转义;严禁拼接字符串(如 '%s'),否则不仅会失败,更会引入 SQL 注入风险。
以下是经过验证的完整、健壮的实现方案:
✅ 推荐写法(安全 + 可维护)
import mysql.connector
import csv
import os
def insert_csv_to_mysql():
csv_path = r"C:\data\LEARNING\PYTHON\excel\MYSQL\texperts\EMPLOYEES.csv"
# 1. 检查文件是否存在
if not os.path.isfile(csv_path):
raise FileNotFoundError(f"CSV 文件未找到: {csv_path}")
# 2. 建立数据库连接(请替换为你的实际凭证)
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="your_password",
database="texperts",
autocommit=False # 关键:关闭自动提交,手动控制事务
)
mycursor = mydb.cursor()
try:
with open(csv_path, encoding='utf-8') as f:
reader = csv.reader(f)
# 3. 跳过表头(第一行)
next(reader, None)
# 4. 预编译 SQL(提升性能,避免重复解析)
sql = """
INSERT INTO employee (
emp_id, emp_init, first_name, last_name, email, phone, role_id
) VALUES (%s, %s, %s, %s, %s, %s, %s)
"""
# 5. 逐行执行插入(生产环境建议改用 executemany 提升性能)
for i, row in enumerate(reader, start=1):
if len(row) != 7:
print(f"警告:第 {i} 行字段数异常(期望 7,实际 {len(row)}),已跳过: {row}")
continue
mycursor.execute(sql, row)
print(f"✓ 已插入第 {i} 条记录: {row}")
# 6. 显式提交事务(关键!否则数据不会持久化)
mydb.commit()
print("✅ 所有记录插入成功,并已提交事务。")
except mysql.connector.Error as e:
# 7. 出错时回滚,保证数据一致性
mydb.rollback()
print(f"❌ 数据库错误: {e}")
raise
except Exception as e:
mydb.rollback()
print(f"❌ 未知错误: {e}")
raise
finally:
# 8. 清理资源
mycursor.close()
mydb.close()
if __name__ == "__main__":
insert_csv_to_mysql()⚠️ 关键注意事项
- 禁止在 SQL 中给 %s 加引号:VALUES('%s',...) 是错误写法;应为 VALUES(%s,...)。MySQL Connector/Python 会自动根据参数类型(int/str/None)进行安全转义。
- 必须调用 mydb.commit():mysql.connector 默认不自动提交,仅 mydb.commit() 或设置 autocommit=True 才能落盘。
- 务必跳过 CSV 表头:使用 next(reader),否则首行字段名(如 "emp_id")会被当作字符串值插入,导致类型错误或主键冲突。
-
推荐使用 executemany() 批量插入(适用于万级以下数据):
rows = list(reader) # 读取全部(注意内存) next(rows) # 跳过表头 mycursor.executemany(sql, rows)
- 字符编码统一:打开 CSV 时显式指定 encoding='utf-8',避免中文或特殊字符乱码。
- 邮箱中的 HTML 标签需清洗:示例 CSV 中的 是反爬邮箱保护格式,真实场景需用正则或 BeautifulSoup 提取纯邮箱地址,否则会插入无效 HTML。
✅ 验证是否成功?
执行后可快速验证:
立即学习“Python免费学习笔记(深入)”;
SELECT * FROM employee ORDER BY emp_id DESC LIMIT 5;
掌握以上要点,你就能稳定、安全地完成 CSV 到 MySQL 的数据导入任务。记住:参数化查询 + 显式事务 + 资源清理 = 可靠数据操作的黄金三角。










