在一个数据表中插入数据,防止有重复的数据插入,一般DBA大多的做法是

唯一索引,主键,在重复的数据插入的过程中,就通过数据库的唯一约束或检查,将这些重复的数据拒之门外。

       而很多场合下,这样的作法并不合适,因为你遇到的程序员他可能不大会处理在数据拒绝插入的后续处理,这是比较尴尬的问题。如何能让他用很简单的SQL语句,来将这个问题解决,这需要 DBA 做点什么。

____________________________________________________________

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据

在SQL SERVER 中一般的情况是这样使用的,(看下面的语句),通过在插入的过程中,进行判断,判断插入tbl_A 来自于 tbl_B的数据不应该和 tbl_A重复,也就是在插入的前边要来一次机遇标识键的过滤

INSERT tbl_A (col, col2)   SELECT col, col2   FROM tbl_B   WHERE NOT EXISTS (SELECT col FROM tbl_A A2 WHERE A2.col = tbl_B.col);


这样看着比较LOW 其实效率也一般。 所以微软推荐的方法是下面的

 Merge 功能,这个功能的在我工作的十几年的经历中,是比较少的,因为大多数的场景在现在的应用开发中,CRUD 的操作已经能覆盖大部分数据库操作的功能,大部分的计算和判断的功能大多是在应用层来做的,通过程序来实践,数据库越来越多变得像一个容器被使用,数据库只要做好MVCC,ISOLATE的事情就OK 了, 所以MERGE 的功能比较少的被引用到数据库的使用中。


而何时要使用MERGE 功能,最近的一个项目的修改中,就遇到了,在原先的数据插入,使用了游标,这样的结果可想而知,一定是糟糕的,数据库使用游标本来就是下下的选择,如果一个程序员使用了游标,除非数据量很小,并且逻辑非常复杂,而且必须要用数据库 PROCEDURE 来做,否则游标应该被踢出数据库的语句层。


在修改后的存储过程中,已经没有了游标,这是一个可喜的事情,但不好的事情又发生了,程序的逻辑中,需要判断插入的数据是否已经在数据库中存在,如果存在,就不要插入,否则就插入。


当然要解决这个问题,其实方法很多,相应的每种方法的限制也不少。


1  唯一索引,联合唯一索引 (被回绝,顾问提供的存储过程是不会使用这样的方法来处理那些中断,错误,使用这样的方法还是要程序报错,目的没有达到) PASS


2  insert into  ....... select ......  where not exist (select .... ) 这个就不说了,上面已经有这样的语句了


3 本次的重点,merge into 语句, 我们还拿上面的的语句改写成merge into 来实现。INSERT tbl_A (col, col2)   SELECT col, col2   FROM tbl_B   WHERE NOT EXISTS (SELECT col FROM tbl_A A2 WHERE A2.col = tbl_B.col);

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据_02


改写后,

merge into tab1 as tab1 

using (select id,size_2 from tab2) as tab2  on tab1.id_1 = tab2.id  

WHEN NOT MATCHED THEN 

insert (size_1) values (size_2);

结果:在没有报错的情况下,将两个表重合的记录去除后,在将不同的结果插入。

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_sql_03

问题解决


——————————————————————————————————

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_sql_04

MYSQL

在MYSQL 中,处理这样的事情比SQL SERVER的方法要多,主要有两种


REPLACE INTO


2 DUPLICATE KEY UPDATE


以上两种方法,在这样的情况下,使用 DUPLICATE KEY UPDATE 是比较合适的,具体Replace into

这里就不在介绍,这两个区别也是显而易见的,一个 匹配 DELETE  ,在INSERT ,另一个是 匹配UPDATE

这是明显的两个方式的不同。


这里还是MYSQL的两个类似SQL SERVER 表

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_sql_05避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据_06



还是要将 tab2 的与 tab1 不同的数据插入到 tab1

insert into tab1 (id,name) select id,name_2 from tab2 on duplicate key update  tab1.name= tab2.name_2;


以上的一条语句就可以完成这个工作,根据主键或者唯一索引,来判断重复的数据,并紧紧进行更新,否则就插入tab1中在tab2中不存在的数据。

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据_07

对比 SQL SERVER , MySQL在这项工作中显然是要方便的多。


——————————————————————————————

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据库_08

ORACLE  在处理这样数据的方式和SQL SERVER 类似,


merge into tab1 using tab2 on (tab1.id=tab2.id) when not matched then insert (id,name) values (tab2.id,tab2.name_2);

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据_09


_____________________________________________________________

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据_10

Postgresql 简述: Postgresql 的确是数据库界的黑马,无论是MYSQL的 

 duplicate key update ,还是 ORACLE  SQL SERVER 支持的 MERGE INTO 语法均在数据库中支持(11版本)

——————————————————————————————————总结:

相比MYSQL ,SQL SERVER 和ORACLE 在处理重复值上比较麻烦,虽然SQL SERVER 和ORACLE 在处理的路数上近似一致,但也有不同点,PostgreSQL 的确是后来者居上,三种数据库支持的方式均在最新版的数据库中支持

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据_11

1 ORACLE 胜出,在MATCH 下的语句还是可以添加 where 条件,这样操作会更灵活,SQL SERVER 不可以

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据_12

2 SQL SERVER 胜出, SQL SERVER 可以在判断中,将目标表未操作的数据删除,但ORACLE 不可以

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据_13

3 MYSQL 在使用中针对去重记录,是最简便最快速的,但功能简单,如果要进行ORACLE 或者 SQL SERVER 复杂的功能,则没有现成的语句完成。

避免 Duplicate key 在数据表插入中的应用(SQL SERVER MYSQL Oracle PostgreSQL)_数据库_14

4  PostgreSQL,胜出,三种数据库支持的方法均都支持,缺点,需要更新的 11版本的PostgreSQL.