mysql 中 insert 的ON DUPLICATE KEY UPDATE

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/scropio0zry/article/details/80752066

平时我们在设计数据库表的时候总会设计 unique  或者 给表加上 primary key 的限制条件。

此时插入数据的时候,经常会有这样的情况:

我们想向数据库插入一条记录:

    若数据表中存在以相同主键的记录,我们就更新该条记录,否则就插入一条新的记录。

逻辑上我们需要怎么写:

$result = mysql_query('select * from xxx where id = 1');
$row = mysql_fetch_assoc($result);
if($row){
mysql_query('update ...');
}else{
mysql_query('insert ...');
}

但是这样写有两个问题

1、效率太差,每次执行都要执行2个sql

2、高并发的情况下数据会出问题,不能保证原子性

    还好MySQL 为我们解决了这个问题:我们可以通过 ON DUPLICATE KEY UPDATE  达到以上目的, 且能保证操作的原子性和数据的完整性。

ON DUPLICATE KEY UPDATE 可以达到以下目的:

1、向数据库中插入一条记录。

2、若该数据的主键值/ UNIQUE KEY已经在表中存在,则执行更新操作, 即UPDATE 后面的操作,否则插入一条新的记录。

例如:

INSERT INTO t_stock_chg(f_market, f_stockID, f_name) VALUES('SH', '600000', '白云机场') ON DUPLICATE KEY UPDATE f_market='SH', f_name='浦发银行'; 

    这条语句如果记录不存在,插入该记录;存在将f_market改为SH,f_name改为浦发银行。现在有个问题是:这条语句判断该条记录是否存在的标准是什么?由于同一个值是可以同时出现在多个记录中的,所以必须有个字段是唯一不能重复的。

    规则是这样的:如果你插入的记录导致一个UNIQUE索引或者primary key(主键)出现重复,那么就会认为该条记录存在,则执行update语句而不是insert语句,反之,则执行insert语句而不是更新语句。所以 ONDUPLICATE KEY UPDATE是不能写where条件的,例如如下语法是错误的:

INSERT INTO t_stock_chg(f_market, f_stockID, f_name) VALUES('SH', '600000', '白云机场') ON DUPLICATE KEY UPDATE f_market='SH', f_name='浦发银行' WHERE f_stockID='600000';

    因为由UNIQUE索引或者主键保证唯一性,不需要WHERE子条件。所以上面的INSERT INTO t_stock_chg(f_market, f_stockID, f_name) VALUES('SH','600000', '白云机场') ON DUPLICATE KEY UPDATE f_market='SH', f_name='浦发银行';中f_stockID就是唯一主键。

    这里特别需要注意的是:如果行作为新记录被插入,则受影响行的值为1;如果原有的记录被更新,则受影响行的值为2,如果更新的数据和已有的数据一模一样,则受影响的行数是0,这意味着不会去更新,也就是说即使你有的时间戳是自动记录最后一次的更新时间,这个时间戳也不会变动。例如:

CREATE TABLE `t_stock_chg` (  
  `f_market` varchar(64) NOT NULL COMMENT '市场',  
  `f_stockID` varchar(10) NOT NULL DEFAULT '' COMMENT '股票代码',  
  `f_updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '插入时间戳',  
  `f_name` varchar(16) DEFAULT NULL COMMENT '股票名称',  
  PRIMARY KEY (`f_market`,`f_stockID`)  
) ENGINE=MyISAM DEFAULT CHARSET=utf8

    这里的字段f_updatetime每次在更新数据时会自动更新,但是如果记录中存在某条数据,后来又更新它,而更新的数据和原数据一模一样,那么这个字段也不会更新,仍然是上一次的时间。此时INSERT ... ON DUPLICATE KEY UPDATE影响行数是0。





猜你喜欢

转载自blog.csdn.net/scropio0zry/article/details/80752066