2015年1月21日 星期三

MySQL REPLACE INTO和INSERT INTO ... ON DUPLICATE KEY UPDATE區別


這兩種方式的作用是如果資料庫中存在記錄就更新,否則就插入新記錄,但是在使用上也是有一點區別的
  總結如下:
1. 如果表中不存在主鍵記錄,REPLACE和INSERT*UPDATE都與INSERT是一樣的特點。
2. 如果表中存在主鍵記錄,REPLACE相當於執行DELETEINSERT兩條操作,而INSERT*UPDATE的相當於執行if exist do update else do insert操作。因此,如果REPLACE填充的字段不全,則會導致未被更新的字段都會修改為默認值,並且如果有自增ID的話,自增ID會變化為最新的值(這樣如果是以自增ID為標誌的話可能導致記錄丟失);而INSERT*UPDATE只是更新部分字段,對於未被更新的字段不會變化(不會強制修改為默認值)。

測試:
建一張表:
-- 資料表結構 `user`
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- 初始資料 `user`

INSERT INTO `user` (`id`, `name`, `phone`, `update_time`) VALUES
(1, 'bear', '12345', NOW()),
(2, 'ted', '54321', NOW());

-- 資料表索引 `user`
ALTER TABLE `user`
 ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `phone` (`phone`);

使用replace into更新
mysql > replace into user(id, name) select 1, 'bear new_name';
結果:
+----+---------------+-------------+---------------------+
| id | name          | phone       | update_time         |
+----+---------------+-------------+---------------------+
|  1 | bear new_name |             | 2015-01-21 15:20:08 |
|  2 | ted           | 54321       | 2015-01-21 14:36:33 |
+----+---------------+-------------+---------------------+
沒填的欄位phone會變成預設值,會先執行delect再insert

使用INSERT INTO ... ON DUPLICATE KEY UPDATE更新
mysql > insert into user(id) select '2' on duplicate key update name='ted new_name';
結果:
+----+---------------+-------+---------------------+
| id | name          | phone | update_time         |
+----+---------------+-------+---------------------+
|  1 | bear new_name |       | 2015-01-21 15:20:08 |
|  2 | ted new_name  | 54321 | 2015-01-21 15:25:54 |
+----+---------------+-------+---------------------+
沒填的欄位不會被取代成預設值

使用INSERT INTO ... ON DUPLICATE KEY UPDATE新增資料
mysql > insert into user(id, name, phone) select NULL, 'wes', '56789' on duplicate key update name='wes new_name', phone='98765';
結果:
+----+---------------+-------+---------------------+
| id | name          | phone | update_time         |
+----+---------------+-------+---------------------+
|  1 | bear new_name |       | 2015-01-21 15:20:08 |
|  2 | ted new_name  | 54321 | 2015-01-21 15:25:54 |
|  3 | wes           | 56789 | 2015-01-21 15:28:55 |
+----+---------------+-------+---------------------+
新增的資料會是select裡面的資料而不是update後面的資料

參考資料:
http://www.blogjava.net/xylz/archive/2010/06/23/324242.html

沒有留言:

張貼留言