mysql不存在插入否则更新

本文介绍使用SQL语句实现数据的更新或插入操作,包括如何通过唯一索引判断记录是否存在并进行相应操作,以及如何在不满足条件时执行插入。通过具体示例展示了两种常见场景下的SQL实现。

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

1.如果存在就更新,没有就插入,相当于三目运算

CREATE UNIQUE INDEX xxx ON t_msg_user_view(USER_ID);

INSERT INTO xxx(user_id,create_time,update_time,STATUS) VALUE('1001',NOW(),NOW(),1)
ON DUPLICATE KEY UPDATE update_time= NOW(),STATUS=1

2.如果不满足就执行insert

INSERT INTO xxx(USER_ID, USER_NAME, VIEW_LEVEL, CREATE_TIME, OPERATOR, STATUS)
SELECT :userId, :userName, :viewLevel, now(), :operator, 1
WHERE NOT EXISTS(SELECT USER_ID FROM xxxWHERE USER_ID=:userId AND STATUS = 1)

转载于:https://www.cnblogs.com/cxhfuujust/p/10190903.html

<think>我们正在讨论MySQL中的"upsert"操作(存在更新存在插入)。根据引用内容,有两种主要方法:`REPLACE INTO`和`INSERT ... ON DUPLICATE KEY UPDATE`(推荐使用后者)。 引用[1]指出:`REPLACE INTO`会先删除旧记录再插入新记录,这可能导致性能问题(尤其是当表有外键或触发器时)。而`INSERT ... ON DUPLICATE KEY UPDATE`则是在主键或唯一索引冲突时执行更新操作,会删除原记录,因此更高效。 引用[2]和[3]进一步说明了`ON DUPLICATE KEY UPDATE`的用法,特别是批量操作时,以及如何更新字段(例如自增字段)。 因此,推荐使用`INSERT ... ON DUPLICATE KEY UPDATE`语法。 步骤: 1. 确保表中存在主键或唯一索引(UNIQUE KEY),因为该操作依赖这些来判断是否重复。 2. 编写INSERT语句,并在后面添加`ON DUPLICATE KEY UPDATE`子句,指定当冲突时需要更新的字段。 示例: 假设有一个表`users`,有字段`id`(主键),`name`,`email`(唯一索引),`age`。 我们想要插入一条记录,如果`email`冲突(即已存在相同的email),则更新该记录的`name`和`age`。 SQL语句如下: ```sql INSERT INTO users (id, name, email, age) VALUES (1, 'John', 'john@example.com', 30) ON DUPLICATE KEY UPDATE name = VALUES(name), age = VALUES(age); ``` 注意: - 这里通过唯一索引`email`判断重复(因为主键id也可能冲突,但这里我们假设id是自增的,通常会在插入时指定,或者指定了也可能冲突)。 - 在`ON DUPLICATE KEY UPDATE`子句中,我们使用`VALUES(column_name)`来引用INSERT语句中准备插入的值。 - 也可以直接指定值,例如:`name = 'John'`,但使用`VALUES(name)`可以确保使用INSERT中提供的值。 另一种情况:如果冲突时需要更新多个字段,可以全部列出。另外,如果只想更新部分字段,也可以只写那些需要更新的字段。 批量操作: 引用[2]提到,该语法也支持批量插入更新。例如: ```sql INSERT INTO users (id, name, email, age) VALUES (1, 'John', 'john@example.com', 30), (2, 'Jane', 'jane@example.com', 25) ON DUPLICATE KEY UPDATE name = VALUES(name), age = VALUES(age); ``` 性能: 引用[3]给出了一个使用该语句进行计数字段自增的例子,说明这种操作是原子性的,适合计数场景。 因此,总结如下: - 使用`INSERT ... ON DUPLICATE KEY UPDATE`实现upsert操作。 - 需要确保有唯一性约束(主键或唯一索引)。 - 在更新部分,可以使用`VALUES(column_name)`来引用插入值。 注意:`REPLACE INTO`虽然也可以实现,但因为它会先删除再插入,可能导致自增主键改变(比如自增ID会变),并且会触发必要的删除和插入操作,影响性能,所以推荐。 相关问题: 1. 如何为表添加唯一索引以确保upsert操作正确执行? 2. 在`ON DUPLICATE KEY UPDATE`子句中,如何更新为特定值而插入的值? 3. 使用upsert操作时,如何避免自增主键的无谓增长? 4. 批量upsert操作时需要注意什么?</think>### MySQL Upsert操作详解 在MySQL中实现"存在更新存在插入"的操作称为**Upsert**。根据您提供的引用信息,推荐使用`INSERT ... ON DUPLICATE KEY UPDATE`语法,这是最高效的实现方式。 #### 核心语法 ```sql INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1, 值2, ...) ON DUPLICATE KEY UPDATE 字段1 = 新值1, 字段2 = 新值2; ``` #### 实现步骤 1. **确保存在唯一约束**(必备条件): - 主键(PRIMARY KEY) - 唯一索引(UNIQUE INDEX) - 组合唯一约束 ```sql ALTER TABLE 表名 ADD UNIQUE INDEX idx_unique (字段1, 字段2); ``` 2. **执行Upsert操作**: ```sql -- 示例:用户表存在更新积分,存在插入 INSERT INTO users (id, name, score) VALUES (101, '张三', 100) ON DUPLICATE KEY UPDATE score = VALUES(score) + 10; -- 冲突时积分+10 ``` 3. **批量操作**(高效方式): ```sql INSERT INTO products (sku, stock) VALUES ('P1001', 50), ('P1002', 30), ('P1003', 20) ON DUPLICATE KEY UPDATE stock = VALUES(stock); ``` #### 性能对比 | 方法 | 特点 | 性能 | |-------------------------------|----------------------------------------------------------------------|--------| | `ON DUPLICATE KEY UPDATE` | 直接更新记录,删除原有数据 | ★★★★★ | | `REPLACE INTO` | 先删除旧记录再插入新数据,触发级联删除 | ★★☆☆☆ | | 先查询再选择插入/更新 | 需要两次数据库交互 | ★☆☆☆☆ | #### 使用技巧 1. **引用插入值**: `VALUES(字段名)`获取插入语句中的值 ```sql ON DUPLICATE KEY UPDATE views = views + VALUES(views) ``` 2. **条件更新**: ```sql ON DUPLICATE KEY UPDATE price = IF(VALUES(price) > 0, VALUES(price), price) ``` 3. **自增字段处理**: 使用`LAST_INSERT_ID()`避免自增ID跳跃 ```sql INSERT ... ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id) ``` #### 注意事项 1. 必须存在唯一约束,否则会变成纯插入操作 2. 更新时会触发`BEFORE UPDATE`触发器 3. 返回结果: - 新插入:返回`1`(受影响行数) - 更新:返回`2`(删除旧行+插入新行计数) 4. 在高并发场景建议使用事务 > 示例:计数器场景[^3] > ```sql > INSERT INTO page_views (page_id, date, views) > VALUES (123, CURDATE(), 1) > ON DUPLICATE KEY UPDATE views = views + 1; > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值