MYSQL 无重复插入数据更新语法 sql一句话使insert时若主键重复则更新

本文详细介绍了MySQL中INSERT...UPDATE语句的使用方法,特别是ON DUPLICATE KEY UPDATE子句的功能和注意事项,包括如何处理唯一键冲突,以及VALUES()函数的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果你指定了ON DUPLICATE KEY UPDATE命令语句,那么在唯一索引或者主索引的作用下将插入与数据库记录重复的内容,但同时会更新数据库中的旧记录。例如,字段a被声明为唯一索引并且里面只包含有值为1的记录,以下两个语句会达到同样的效果:

一、INSERT INTO table (a,b,c) VALUES (1,2,3)
   ON DUPLICATE KEY UPDATE c=c+1;

二、UPDATE table SET c=c+1 WHERE a=1;

受影响的是a=1的行,当插入时c的值加1。
如果字段b也是唯一的话,这个插入语句将和以下语句的效果一样:
UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
如果a=1 OR b=2匹配了不止一行,也只是第一行被更新。一般地,如果表中有多个唯一索引的话,你应该避免在使用用ON DUPLICATE KEY子句。
你可以在插入更新语句 INSERT ... UPDATE 中使用 VALUES(字段名) 函数去关联某一行记录。也就是说, VALUES(字段名) 可以用在UPDATE语句中去更新某字段的值而会出现重复键。这个函数在多行插入中尤其有用。但是函数 VALUES() 仅当用在 INSERT ... UPDATE 语句中才有意义,否则会返回NULL。例如:

INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

这个语句和下面两个是同效果的:

INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=3;
INSERT INTO table (a,b,c) VALUES (4,5,6)
ON DUPLICATE KEY UPDATE c=9;

如果表中包含有一个自动递增字段AUTO_INCREMENT,并用 INSERT ... UPDATE 插入一行,函数 LAST_INSERT_ID()会返回AUTO_INCREMENT的值,如果这个语句更新某一行, LAST_INSERT_ID() 就没有意义了。但是,你可以通过用 LAST_INSERT_ID(expr)使它变得有意义,假如id字段是自动递增栏的话,使 LAST_INSERT_ID() 对更新语句有意义的方法如下:

INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

如果你使用 ON DUPLICATE KEY UPDATE 语句的话,延迟执行选项 DELAYED 将被忽略。

英文原文地址:http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

其它声音:

插入记录

Insert into table_name (field_name1, field_name2, …) values (value1, value2, …);

Insert into values (value1, value2, …);   //这种形式只能应用于值的顺序与字段顺序匹配的情况(可以通过调用describe命令来决定字段顺序)。
包含引用标志的值需要再引号’前面加上反斜线                   //转义字符
注意:into 关键字是可选的
也可以同时插入多个值,用逗号分开
Eg:insert table_name values (value1, value2, …), (value3, value4, …);
还可以不使用insert… values格式,而使用类似update语句,它使用set子句分别为每一列设置值。
Insert into table_name set field_name1 = value1, field_name2 = value2,…;
使用default值
Create table table_name (field_name1 type default def_value not null,…);
Insert table_name values (default,…);   //default关键字只在4.0.3以及更高版本才支持
使用AUTOINCREMENT字段
自动产生下一个序号,该字段必须被设置为主键
使用UNIQUE字段
使用IGNORE关键字或者ON DUPLICATE KEY UPDATE子句跳过INSERT、中断操作或者更新旧记录为新值。
INSERT IGNORE INTO TABLE_NAME (UNIQUE_FIELD, …) VALUES (REPEAT, …);
如果重复记录,则不会报告错误,也不会更新记录,数据库中的数据保持不变。
ON DUPLICATE KEY UPDATE和REPLACE区别:前者只把已命名的字段更新为新值,后者删除了旧记录,然后用新值完全替换。
Eg:insert into Menu value (null, ‘MySQL’, ‘www.mysql.com’) on duplicate key update label=’MS SQL’, url=’www.microsoft.com’;
在这种情况下,如果MySQL发现表中已经包含具有相同唯一键的记录,则会自动更新旧的记录为ON DUPLICATE KEY UPDATE从句中指定的新值。
当有很多insert语句需要被顺序执行时,IGNORE关键字就使操作变得很方便。这可以保证不管拿一个INSERT包含了重复值,MySQL都会跳过而不放弃全部操作。

<think>我们参考了用户提供的引用内容,特别是引用[1]和引用[3]中关于`INSERT IGNORE`的说明。在MySQL中,`INSERT IGNORE`语句可以忽略插入数据遇到的重复主键错误,而不会中断整个插入操作。在Python中,我们可以使用pymysql库来执行SQL语句。 用户的需求是:在使用Python向MySQL数据库插入数据,忽略由于主键重复而导致的错误。 解决方案: 1. 在SQL语句中使用`INSERT IGNORE INTO ...`语法。 2. 使用参数化查询来避免SQL注入,并执行该SQL语句。 步骤: a. 连接数据库。 b. 创建游标对象。 c. 编写`INSERT IGNORE`语句。 d. 执行语句,并提交事务。 e. 关闭连接。 注意:`INSERT IGNORE`会忽略所有错误(包括重复主键)吗?根据MySQL文档,它会忽略可忽略的错误(如重复键、数据类型转换错误等),但有些错误(如表不存在)仍然会抛出。 示例代码: 假设我们有个表`students`,其主键为`id`,字段包括`id`和`name`。 我们想要插入条记录,如果主键已存在,则忽略该插入操作。 代码实现如下:</think># 在 Python 中实现 MySQLINSERT IGNORE 功能 在 Python 中使用 `INSERT IGNORE` 语句可以优雅地处理主键重复问题,避免因重复键导致的插入失败。以下是完整实现方案: ## 核心解决方案 ### 1. 使用 `INSERT IGNORE` SQL 语句 ```python import pymysql def insert_ignore_duplicate(host, user, password, db, table, data_dict): """插入数据并忽略主键重复错误""" try: # 连接数据库 connection = pymysql.connect( host=host, user=user, password=password, database=db, cursorclass=pymysql.cursors.DictCursor ) with connection: with connection.cursor() as cursor: # 动态生成SQL columns = ', '.join(data_dict.keys()) placeholders = ', '.join(['%s'] * len(data_dict)) sql = f"INSERT IGNORE INTO {table} ({columns}) VALUES ({placeholders})" # 执行参数化查询 cursor.execute(sql, tuple(data_dict.values())) # 提交事务 connection.commit() return cursor.rowcount # 返回受影响的行数 except pymysql.Error as e: print(f"数据库错误: {e}") return 0 ``` ### 2. 使用示例 ```python # 示例数据 student_data = { 'id': 1001, # 主键 'name': '张三', 'age': 20, 'email': 'zhangsan@example.com' } # 执行插入 result = insert_ignore_duplicate( host='localhost', user='root', password='your_password', db='school', table='students', data_dict=student_data ) if result == 1: print("数据插入成功") elif result == 0: print("主键已存在,数据插入") ``` ## 高级用法:获取最后插入的ID ```python def insert_ignore_with_id(host, user, password, db, table, data_dict): """插入数据并返回最后插入的ID(忽略重复)""" try: connection = pymysql.connect( host=host, user=user, password=password, database=db ) with connection: with connection.cursor() as cursor: # 生成SQL columns = ', '.join(data_dict.keys()) placeholders = ', '.join(['%s'] * len(data_dict)) sql = f""" INSERT IGNORE INTO {table} ({columns}) VALUES ({placeholders}) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id) """ # 执行插入 cursor.execute(sql, tuple(data_dict.values())) # 获取最后插入的ID cursor.execute("SELECT LAST_INSERT_ID()") last_id = cursor.fetchone()[0] connection.commit() return last_id except pymysql.Error as e: print(f"数据库错误: {e}") return None ``` ## 关键机制说明 1. **`INSERT IGNORE`工作原理**: - 当插入数据遇到重复主键或唯键冲突 - MySQL 会忽略该行插入操作而不是报错中断 - 返回受影响行数为 0 - 生成警告而非错误[^1][^3] 2. **`ON DUPLICATE KEY UPDATE`**: - 可选的扩展语法 - 当遇到重复执行更新操作 - `LAST_INSERT_ID(id)` 确保获取正确的ID[^2] 3. **Python实现要点**: - 使用参数化查询防止SQL注入 - 事务管理确保数据致性 - 异常处理增强健壮性 ## 批量插入处理 ```python def bulk_insert_ignore(host, user, password, db, table, data_list): """批量插入并忽略重复记录""" try: connection = pymysql.connect( host=host, user=user, password=password, database=db ) with connection: with connection.cursor() as cursor: if not data_list: return 0 # 生成SQL columns = ', '.join(data_list[0].keys()) placeholders = ', '.join(['%s'] * len(data_list[0])) sql = f"INSERT IGNORE INTO {table} ({columns}) VALUES ({placeholders})" # 准备数据 values = [tuple(item.values()) for item in data_list] # 执行批量插入 cursor.executemany(sql, values) connection.commit() return cursor.rowcount # 返回实际插入的行数 except pymysql.Error as e: print(f"批量插入错误: {e}") connection.rollback() return 0 ``` ## 实际应用场景 1. **数据同步**:从外部系统同步数据忽略重复记录 2. **日志记录**:避免重复记录相同事件 3. **用户注册**:防止用户名/邮箱重复注册 4. **物联网数据**:处理设备重复上报的数据 通过使用 `INSERT IGNORE`,您可以构建更健壮的数据插入逻辑,有效处理主键冲突问题而不中断程序执行[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值