数据库存在相同数据时如何覆盖或跳过?文本文件导入MySQL去重方案
现有代码问题分析
- 插入SQL中共包含5个
%s占位符:前4个对应待插入的a、b、c、d四个字段,第5个用于重复校验匹配a字段,但你传入执行的field参数仅包含拆分后得到的4个元素,参数数量不匹配导致去重逻辑完全失效 - 插入前全表查询
select * from ftp的操作属于多余逻辑,数据量大时会严重占用内存、拖慢执行效率 - 用子查询判断是否存在重复值的方案,性能远低于数据库原生的唯一索引约束方案,高并发场景下还可能出现幻读导致重复插入
修复方案
方案1:适配现有逻辑修复(无需调整表结构)
补全参数数量,同时增加脏数据校验逻辑,避免异常行导致程序崩溃,修改后完整代码如下:
import mysql.connector from mysql.connector import Error text_file = open(min_file, "r") for line in text_file: # 去除行首尾空白、跳过空行 line = line.strip() if not line: continue field = line.split(";") # 校验字段数量,跳过异常行 if len(field) != 4: print(f"跳过格式异常行:{line}") continue print(field) try: connection = mysql.connector.connect(host='localhost', database='testing', user='root', password='root') if connection.is_connected(): db_Info = connection.get_server_info() print("Connected to MySQL Server version ", db_Info) mycursor = connection.cursor() mycursor.execute("select database();") record = mycursor.fetchone() print("You're connected to database: ", record) # 修复SQL写法,补全参数 sql = "INSERT INTO ftp(a,b,c,d) \ SELECT %s,%s,%s,%s FROM DUAL \ WHERE NOT EXISTS (SELECT a FROM ftp WHERE a = %s) LIMIT 1" # 传入参数增加field[0](a字段值)匹配第5个占位符 mycursor.execute(sql, field + [field[0]]) print(mycursor.rowcount, "record inserted.") connection.commit() except Error as e: print("Error while connecting to MySQL", e) finally: if connection.is_connected(): mycursor.close() connection.close() print("MySQL connection is closed")
方案2:性能更优的唯一索引方案(推荐使用)
利用MySQL原生唯一约束实现去重,可靠性和执行效率都远高于子查询方案:
- 先对ftp表的a字段添加唯一索引,在数据库中执行以下SQL:
ALTER TABLE ftp ADD UNIQUE INDEX `idx_unique_a` (`a`);
- 修改插入语句为
INSERT IGNORE语法,插入时如果a字段重复会自动跳过,无需额外判断逻辑:
sql = "INSERT IGNORE INTO ftp(a,b,c,d) VALUES (%s,%s,%s,%s)" mycursor.execute(sql, field)
该方案优势:
- 数据库原生约束,避免并发插入场景下的幻读问题,完全不会出现重复数据
- 代码逻辑更简洁,无需写复杂的嵌套子查询
- 执行效率更高,表数据量越大性能优势越明显
内容的提问来源于stack exchange,提问作者Kaung Sat
相关产品推荐
相关产品推荐

