日期:2014-05-16 浏览次数:20863 次
以下讨论全部针对Mysql数据库:)
?
通常业务上至少需要两种类型的不重复插入记录的需求:
?
1、针对上面的第一种,mysql提供了insert into ... on duplicate key update ... 语法(Mysql自己的语法,不属于标准SQL)来实现。这种场景相对常见。使用的前提是,需要定义主键或者唯一性索引,用来告诉Mysql哪些字段的重复会造成主键冲突或者违背唯一性约束条件。当这些情况出现时,就放弃insert操作,转而执行后面的update操作。上一个具体的例子,在ibatis中写的一个上面逻辑的sql:
?
<statement id="testInsertOnDuplicateKeyUpdate" parameterClass="com.alibaba.ais.bdc.person.dataobject.UserInfo"> <!--Here the employ_id has been defined as a primary key--> insert into T_USER_INFO (employ_id,fans_count,follow_count) values (#employId#,#fansCount#,#followCount#) ON DUPLICATE KEY UPDATE follow_count=follow_count+1 </statement>
上面的插入操作就会在employ_id发生主键冲突的时候,转变为更新follow_count字段(自增一个单位)。
?
2、针对上面的第二种,mysql提供了insert ignore into ... 语法(Mysql自己的语法,不属于标准SQL)来实现。这种场景相对要少见一些。?使用的前提是,需要定义主键或者唯一性索引,原因同上面一致。但不同的就是,违背唯一性约束时,直接忽略这次insert操作,然后啥也不干了,也不会报错。。。
但这里有个问题,就是有时业务本身还是需要知道语句到底执行了insert还是没有执行!因为需要根据这个反馈信息,做出不同的处理逻辑。这里给出使用ibatis时,两种不同的处理方法。
?
<insert id="testSelectKey"> insert into T_TEST(WATCHER, WATCHEE) values (#watcher#,#watchee#) <selectKey resultClass="int" keyProperty="id"> select last_insert_id() as ID from dependency limit 1 </selectKey> </insert>?
Integer id = (Integer) sqlMapClient.insert("testSelectKey", param);??
<insert id="testInsertIgnore"> insert ignore into T_TEST(WATCHER, WATCHEE) values (#watcher#,#watchee#) <selectKey resultClass="int" keyProperty="id"> select row_count() as ID from T_USER_RELATION limit 1 </selectKey> </insert>通过上面语句进行插入操作之后,可以通过如下方式在Java代码中获得insert真正影响到的行数:
Integer affectedRows = (Integer)sqlMapClient.insert("testInsertIgnore", param);?
<update id="testInsertIgnore"> insert ignore into T_USER_RELATION(WATCHER, WATCHEE) values (#watcher#,#watchee#) <!--Without selectKey tag, it looks mush more concise--> </update>?通过上面语句进行插入操作之后,可以通过如下方式在Java代码中获得insert真正影响到的行数(这里需要注意的是,Java代码中需要使用sqlMapClient的update的API哦):
Integer affectedRows = (Integer)sqlMapClient.update("testInsertIgnore", param);?