Mysql避免重复插入记录方法
Posted 贪梦好
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql避免重复插入记录方法相关的知识,希望对你有一定的参考价值。
一、mysql replace用法
1.replace into
replace into table (id,name)
values(‘1‘,‘aa‘),(‘2‘,‘bb‘)
此语句的作用是向表table中插入两条记录。如果主键id为1或2不存在
就相当于
insert into table (id,name)
values(‘1‘,‘aa‘),(‘2‘,‘bb‘)
如果存在相同的值则不会插入数据
2.replace(object,search,replace)
把object中出现search的全部替换为replace
select
replace(‘www.jb51.net‘,‘w‘,‘Ww‘)--->WwWwWw.jb51.net
例:把表table中的name字段中的aa替换为bb
update table set
name=replace(name,‘aa‘,‘bb‘)
二、try catch异常处理机制
declare continue handler for 1062 set done = 1
注:1062错误是主键字段插入重复的错误。
三 、mysql之INSERT INTO…ON DUPLICATE KEY UPDATE
提供了insert into … on duplicate key update的语法,该语法在insert的时候,如果insert的数据会引起唯一索引(包括主键索引)的冲突,即这个唯一值重复了,则不会执行insert操作,而执行后面的update操作。
注意:ON DUPLICATE KEY UPDATE只是MySQL的特有语法,并不是SQL标准语法!
例如,现在有表test,test表中有字段a,在a上有主键或者唯一索引,并且表中只有一条a=1, b=1的数据,现在执行如下的sql:
insert into test (a,b) values (1,2) on duplicate key update b = b + 1;
注:直接update = ,不能用完整的update语句。
因为a=1的记录已存在了,所以不会执行insert,而会在该条记录上执行update语言`b=b+1`,记录会变成a=1,b=2
insert into test (a,b) values (2,2) on duplicate key update b = b + 1;
因为a=2的记录不存在,所以执行insert
如果行作为新记录被插入,则受影响的行为1;如果原有记录被更新,则受影响行为2;如果原有记录已存在,但是更新的值和原有值相同,则受影响行为0。
多唯一索引冲突的情况说明:
为了测试方便,我们建了下面的数据表:
create table test(
a int not null primary key,
b int not null UNIQUE key,
c int not null
)
输入数据:insert into test values(1,1,1), (2,2,2);
然后执行:insert into test values(1,2,3) on duplicate key update c = c + 1;
因为a和b都是唯一索引,插入的数据在两条记录上产生了冲突,然而执行后只有第一条记录被修改:
mysql> select * from test;
+---+---+---+
| a | b | c |
+---+---+---+
| 1 | 1 | 2 |
| 2 | 2 | 2 |
+---+---+---+
2 rows in set (0.00 sec)
上面的语句等同于:update test set c=c+1 where a=1 or b = 2 limit 1;
如果a=1 or b =2匹配多条记录,只有第一条记录被更新。所以,一般情况下,我们应该避免在有多个唯一索引的表中使用on duplicate key update。
使用values()方法,在update中可以使用values()方法引用在insert中的值,如:
insert into test values(1,3,5) on duplicate key update c = values( c )+ 1;
该语句会使a=1的记录中c字段的值更新为6,因为values(c)的值是引用的insert部分的值,在这个例子中就是insert into test values(1,3,5) 中的5,所以最终更新的值为6。
注意:VALUES()函数只在INSERT...UPDATE语句中有意义,其它时候会返回NULL。
last_insert_id()
如果表含有auto_increment字段,使用insert … on duplicate key update插入或更新后,last_insert_id()返回auto_increment字段的值。
并发控制
在使用例如MyISAM这样的表级锁的分区表上使用insert … on duplicate key update时,会锁住所有分区表,而在例如使用InnoDB这样的行级锁的分区表上则不会锁住所有分区表。
delayed选项
delayed选项会被忽略,当我们使用on duplicate key update时。
四:使用ignore关键字
如果是用主键primary或者唯一索引unique区分了记录的唯一性,避免重复插入记录可以使用:
INSERT IGNORE INTO `table_name` (`email`, `phone`, `user_id`) VALUES (‘[email protected]‘, ‘99999‘, ‘9999‘);
这样当有重复记录就会忽略,执行后返回数字0
还有个应用就是复制表,避免重复记录:
INSERT IGNORE INTO `table_1` (`name`) SELECT `name` FROM `table_2`;
最后贴上一个练习时的sp作为参考之用。
CREATE PROCEDURE Jack_xml_replace(xmlstr LONGTEXT,company_code int) BEGIN declare parentpoint_count int default 0; #声明父节点个数 declare i int default 1; #循环次数,循环结束判定 declare v_bankCd varchar(20); declare v_outletNo varchar(20); declare v_payAmount NUMERIC(10,1); declare v_paymentDate varchar(20); declare v_paymentNum varchar(20); declare v_paymentType varchar(1); declare v_paymentUsage varchar(20); declare v_sourcecode varchar(20); declare v_transactionId varchar(255); set parentpoint_count = ExtractValue(xmlstr,‘count(/o/payList/e)‘); #获取行数 #开始循环 while i <= parentpoint_count do set v_bankCd = ExtractValue(xmlstr,‘/o/payList/e[$i]/bankCd‘); set v_outletNo = ExtractValue(xmlstr,‘/o/payList/e[$i]/outletNo‘); set v_payAmount = ExtractValue(xmlstr,‘/o/payList/e[$i]/payAmount‘); set v_paymentDate = ExtractValue(xmlstr,‘/o/payList/e[$i]/paymentDate‘); set v_paymentNum = ExtractValue(xmlstr,‘/o/payList/e[$i]/paymentNum‘); set v_paymentType = ExtractValue(xmlstr,‘/o/payList/e[$i]/paymentType‘); set v_paymentUsage = ExtractValue(xmlstr,‘/o/payList/e[$i]/paymentUsage‘); set v_sourcecode = ExtractValue(xmlstr,‘/o/payList/e[$i]/sourcecode‘); set v_transactionId = ExtractValue(xmlstr,‘/o/payList/e[$i]/transactionId‘); update jack_xml a set a.bankCd = v_bankCd,outletNo = v_outletNo ,payAmount = v_payAmount ,paymentDate = v_paymentDate ,paymentNum = v_paymentNum ,paymentType = v_paymentType ,paymentUsage = v_paymentUsage ,sourcecode = v_sourcecode where a.company_code=company_code and a.transactionId=v_transactionId; replace into jack_xml(company_code,bankCd,outletNo,payAmount,paymentDate,paymentNum,paymentType,paymentUsage,sourcecode,transactionId) value(company_code,v_bankCd,v_outletNo,v_payAmount,v_paymentDate,v_paymentNum,v_paymentType,v_paymentUsage,v_sourcecode,v_transactionId); set i=i+1; end while; select * from jack_xml; #查看实体表数据 END # 运行参数 CALL Jack_xml_replace(‘ <?xml version="1.0" encoding="utf-8"?> <o> <payList class="array"> <e class="object"> <bankCd type="string">4</bankCd> <outletNo type="string">0510020017</outletNo> <payAmount type="number">200.0</payAmount> <paymentDate type="string">20161212121212</paymentDate> <paymentNum type="string">12323</paymentNum> <paymentType type="string">Y</paymentType> <paymentUsage type="string">B</paymentUsage> <sourcecode type="string">CS</sourcecode> <transactionId type="string">99B2E125-AB09-4AE3-9A05-5FE9876AF799</transactionId> </e> <e class="object"> <bankCd type="string">4</bankCd> <outletNo type="string">0510020017</outletNo> <payAmount type="number">300.0</payAmount> <paymentDate type="string">20161112131415</paymentDate> <paymentNum type="string">23232</paymentNum> <paymentType type="string">Y</paymentType> <paymentUsage type="string">B</paymentUsage> <sourcecode type="string">SFA</sourcecode> <transactionId type="string">99B2E125-AB09-4AE3-9A05-5FE9876AF798</transactionId> </e> </payList> </o>‘,3006);
以上是关于Mysql避免重复插入记录方法的主要内容,如果未能解决你的问题,请参考以下文章
MySql避免重复插入记录方法(ignore,Replace,ON DUPLICATE KEY UPDATE)