Python操作MySQL实现非重复插入及1064语法报错问题求助
报错原因
- 你使用的
IF NOT EXISTS(...) BEGIN ... END是SQL Server专属语法,MySQL不支持该写法,直接运行会触发语法错误。 - 你手动拼接了
account字符串到SQL语句中,字符串类型的字段值没有添加引号,同时还存在SQL注入风险,报错信息里的Account_Name = DE - Kipling DE就是没有引号导致的语法识别错误。
解决方案1(推荐,性能更高):INSERT IGNORE + 唯一索引
这是MySQL实现非重复插入的最高效方案,操作如下:
- 先给
Accounts表的Account_Name字段添加唯一索引,该操作只需执行一次:
ALTER TABLE Accounts ADD UNIQUE INDEX idx_account_name (Account_Name);
- 修改Python代码,使用批量插入提升效率:
# 唯一键冲突时INSERT IGNORE会自动跳过插入,不会抛出错误 sql = "INSERT IGNORE INTO Accounts (Account_Name, Account_ID, Formatted_Name, Crawler_Name) VALUES (%s, %s, %s, %s)" vals = [(account, '0', 'test', 'test') for account in accounts] mycursor.executemany(sql, vals) mydb.commit()
解决方案2(无需修改表结构):INSERT + WHERE NOT EXISTS语法
如果不方便给表加唯一索引,可以使用MySQL原生支持的去重插入语法:
sql = """ INSERT INTO Accounts (Account_Name, Account_ID, Formatted_Name, Crawler_Name) SELECT %s, %s, %s, %s FROM DUAL WHERE NOT EXISTS ( SELECT 1 FROM Accounts WHERE Account_Name = %s ) """ vals = [] for account in accounts: # 参数需要传两次,分别对应SELECT的字段值和WHERE条件的匹配值 vals.append((account, '0', 'test', 'test', account)) mycursor.executemany(sql, vals) mydb.commit()
该方案通过MySQL虚拟表DUAL构造查询来源,当检测到账号已存在时就不会执行插入操作。
注意事项
所有SQL参数都要通过execute/executemany的第二个参数传入,不要手动拼接参数到SQL语句中,既能避免语法错误,也能防范SQL注入风险。
内容的提问来源于stack exchange,提问作者thirddayouthere
相关产品推荐
相关产品推荐

