mysql dual 使用虚拟表实现不重复数据插入

这篇博客探讨了在MySQL中如何在不考虑主键的情况下避免插入重复数据的方法,包括INSERT IGNORE、REPLACE INTO、ON DUPLICATE KEY UPDATE以及利用NOT EXISTS子查询的技巧。这些方法各有特点,例如INSERT IGNORE会忽略重复数据,而ON DUPLICATE KEY UPDATE则允许在冲突时更新已有记录。最后,推荐使用NOT EXISTS结合DUAL表的策略,因为它提供了更大的灵活性来定义唯一性条件。

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

背景:当插入数据时,需要判断某些字段在表中不存在相同的数据,但是id(主键)不做为判断条件

问题1.insert into

          语句会判断主键、unique,当出现重复值时,报错

           2.INSERT IGNORE INTO

          相比insert into 的区别是:INSERT IGNORE会忽略数据库中已经存在 的数据,如果数据库没有数据,就插入新的数据,如果有数据的话就跳过这条数据。这样就可以保留数据库中已经存在数据,达到在间隙中插入数据的目的。

          3.REPLACE INTO 

         如果存在primary or unique相同的记录,则先删除掉。再插入新记录。 
        REPLACE INTO books SELECT 1, 'MySQL Manual' FROM books 
        这种方法就是不管原来有没有相同的记录,都会先删除掉然后再插入。

       4.on duplicate key update 
        当primary或者unique重复时,则执行update语句,如update后为无用语句,如id=id,则同1功能相同,但错误不会被忽略掉。例如,为了实现name重复的数据插入不报错,可使用一下语句: 
       INSERT INTO books (name) VALUES ('MySQL Manual') ON duplicate KEY UPDATE id = id 
       这种方法有个前提条件,就是,需要插入的约束,需要是主键或者唯一约束(在你的业务中那个要作为唯一的判断就将那个字段设置为唯一约束也就是unique key)。

       5.insert … select … where not exist 
      根据select的条件判断是否插入,可以不光通过primary 和unique来判断,也可通过其它条件。例如: 
 insert into test(id,name,password) select 9,"zhangsan1","1234563" from DUAL where not exists(select name from test where name = "zhangsan1" and password="1234563");
       这种方法其实就是使用了mysql的一个临时表的方式,但是里面使用到了子查询,效率也会有一点点影响,如果能使用上面的就不使用这个。

语法:

INSERT INTO table(column1,column2,column3 ...columnN)  
SELECT value1,value2,value3 ...valueN  
FROM dual  
WHERE NOT EXISTS(  
      SELECT *  
      FROM table  
      WHERE value = ?  
); 

结论:使用最后一种方式

### MySQL 插入数据前检查记录是否存在 为了防止向数据库中插入重复的数据,在执行 `INSERT` 操作之前可以先验证目标表内是否已经存在相同的记录。一种常用的方式是在 SQL 语句里嵌套子查询来完成这一逻辑判断。 对于希望实现的功能,即条件性的插入操作——当且仅当某条特定记录存在时才将其加入到指定表格之中,可以通过如下所示的 SQL 语法结构达成目的: ```sql INSERT INTO table_name (column1, column2, ...) SELECT value1, value2, ... FROM DUAL WHERE NOT EXISTS ( SELECT * FROM table_name WHERE condition; ); ``` 这里的关键在于使用了 `DUAL` 表作为占位符,并通过外层的 `WHERE NOT EXISTS (...)` 子句确保只有满足给定条件下才会触发实际的数据插入动作[^1]。 另外还有一种更为简洁的方法是利用 `ON DUPLICATE KEY UPDATE` 或者 `REPLACE INTO` 来处理潜在冲突的情况;过这些方法适用于那些已经在表上设置了唯一索引或主键约束的情形下工作得更好。而针对未设置此类约束但又确实需要避免完全相同行被多次录入的需求,则推荐采用上述带有 `NOT EXISTS` 的方式[^3]。 值得注意的是,某些版本的 MySQL 可能允许直接在 `INSERT ... SELECT` 结构中的 `FROM` 部分省略具体来源表名而是强制要求提供至少一个真实的基表名称,此时可考虑引入虚拟表 `dual` 解决此限制[^4]。 #### 示例代码 假设有一个名为 `users_roles` 的关系型表用于存储用户角色关联信息,其中包含两个字段分别是 `userid` 和 `roleid` 。现在想要往该表新增一条记录 `(userid_x, roleid_x)` ,前提是这条组合尚未存在于当前表单之内: ```sql -- 使用标准SQL语法 INSERT INTO users_roles (userid, roleid) SELECT 'userid_x', 'roleid_x' FROM dual WHERE NOT EXISTS ( SELECT * FROM users_roles WHERE userid = 'userid_x' AND roleid = 'roleid_x'); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值