Python操作SQL数据库插入数据时如何避免出现重复条目
解决方案
方案1:数据库层面添加唯一约束(优先推荐)
通过在表结构中新增唯一组合约束,从根源上避免重复数据插入,并发场景下也安全,不需要额外的查询逻辑,性能更优。
- 优点:并发安全,性能更高,不需要额外的查询逻辑,由数据库原生保证数据唯一性
- 注意:唯一约束的字段组合需要根据业务实际场景定义,确保组合起来可以唯一标识一条行程记录,示例中以
行程日期、行程名称、行程起点作为唯一标识,可自行调整。
第一步:调整建表语句,添加唯一约束
mycursor = mydb.cursor() sql = f"""CREATE TABLE IF NOT EXISTS _{self.client_id} ( tour_date DATE, tour_distance INT, tour_duration INT, tour_elevation_up INT, tour_elevation_down INT, tour_map_image TEXT, tour_name TEXT, tour_sport TEXT, tour_start_point TEXT, tour_type TEXT, -- 新增唯一组合约束 UNIQUE KEY unique_tour (tour_date, tour_name, tour_start_point) )""" mycursor.execute(sql) mydb.commit()
第二步:调整插入语句
如果重复时不需要更新原有数据,直接跳过插入,使用INSERT IGNORE:
mycursor = mydb.cursor() # 插入前自动校验唯一约束,重复则自动跳过,不会抛出异常 sql = f"INSERT IGNORE INTO _{self.client_id} (tour_date, tour_distance, tour_duration, tour_elevation_up, tour_elevation_down, tour_map_image, tour_name, tour_sport, tour_start_point, tour_type) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) " val = (TourDate, TourDistance, TourDuration, TourElevation_up, TourElevation_down, TourMap_image, TourName, TourSport, TourStart_point, TourType) mycursor.execute(sql, val) mydb.commit()
如果重复时需要更新原有数据(比如更新行程距离、时长等字段),使用ON DUPLICATE KEY UPDATE:
mycursor = mydb.cursor() sql = f"""INSERT INTO _{self.client_id} (tour_date, tour_distance, tour_duration, tour_elevation_up, tour_elevation_down, tour_map_image, tour_name, tour_sport, tour_start_point, tour_type) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) -- 重复时更新指定字段,可按需调整要更新的字段 ON DUPLICATE KEY UPDATE tour_distance = VALUES(tour_distance), tour_duration = VALUES(tour_duration), tour_elevation_up = VALUES(tour_elevation_up) """ val = (TourDate, TourDistance, TourDuration, TourElevation_up, TourElevation_down, TourMap_image, TourName, TourSport, TourStart_point, TourType) mycursor.execute(sql, val) mydb.commit()
方案2:插入前先查询校验(适合不便改表结构的场景)
插入前先查询表中是否存在对应条目,不存在才执行插入操作。
- 优点:不需要修改表结构,灵活性高
- 缺点:多一次查询请求,性能低于方案1,高并发场景下可能出现竞态条件导致重复插入,仅推荐低并发、不便修改表结构的场景使用。
代码示例:
mycursor = mydb.cursor() # 先查询是否存在相同条目,查询条件和唯一标识字段保持一致 check_sql = f"SELECT COUNT(*) FROM _{self.client_id} WHERE tour_date = %s AND tour_name = %s AND tour_start_point = %s" check_val = (TourDate, TourName, TourStart_point) mycursor.execute(check_sql, check_val) count = mycursor.fetchone()[0] if count == 0: # 不存在才执行插入 insert_sql = f"INSERT INTO _{self.client_id} (tour_date, tour_distance, tour_duration, tour_elevation_up, tour_elevation_down, tour_map_image, tour_name, tour_sport, tour_start_point, tour_type) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) " insert_val = (TourDate, TourDistance, TourDuration, TourElevation_up, TourElevation_down, TourMap_image, TourName, TourSport, TourStart_point, TourType) mycursor.execute(insert_sql, insert_val) mydb.commit()
内容的提问来源于stack exchange,提问作者Broump
相关产品推荐
相关产品推荐

