MySQL隨筆(四)
mysql 中 replace into 與 insert into on duplicate key update 的使用和不同點
replace into和insert into on duplicate key update都是為了解決我們平時的一個問題
就是如果資料庫中存在了該條記錄,就更新記錄中的資料,沒有,則新增記錄。
我們建立一個測試表test
1 2 3 4 5 6 |
CREATE TABLE `test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID' ,
`name` varchar(32) DEFAULT '' COMMENT '姓名' ,
`addr` varchar(256) DEFAULT '' COMMENT '地址' ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
向該表中插入一些資料
1 2 3 4 5 6 |
INSERT INTO test
VALUES
(NULL, 'a' , 'aaa' ),
(NULL, 'b' , 'bbb' ),
(NULL, 'c' , 'ccc' ),
(NULL, 'd' , 'ddd' );
|
影響行數4,結果如下:
我們執行如下語句:
1 |
REPLACE INTO test VALUES(NULL, 'e' , 'eee' );
|
結果顯示,影響行數1條,記錄被插入成功了
注意上面的語句,我們並沒有填寫主鍵ID。
然後我們再執行下面的語句:
1 |
REPLACE INTO test VALUES(1, 'aa' , 'aaaa' );
|
結果顯示,影響行數2條,ID為1的記錄被更新成功了
為什麼會出現這種情況,原因就是replace into會首先嚐試先往表裡面插入記錄,因為我們的ID是主鍵,不可重複,顯然這條記錄是無法插入成功的,然後replace into會把這條已存在的記錄刪掉,然後再插入,所以會顯示影響行數是2。
我們再執行下面這條語句:
1 |
REPLACE INTO test(id,name) VALUES(1, 'aaa' );
|
這裡我們只指定id,name欄位,我們來看看replace into後addr欄位內容是否還存在
顯然addr欄位內容沒有了,跟我們上面的分析是一致的,reaplce into先刪除了id為1的記錄,然後再插入記錄,但我們並沒有指定addr的值,所以會如上圖所示那樣。
但是有些時候我們的需求是,如果記錄存在則更新指定欄位的資料,原有欄位資料仍保留,而不是上面所示的,addr欄位資料沒有了。
這裡就需要用到insert into on duplicate key update
執行如下語句:
1 2 3 4 5 |
INSERT INTO test (id, name)
VALUES(2, 'bb' )
ON DUPLICATE KEY
UPDATE
name = VALUES(name);
|
VALUES(欄位名)表示獲取當前語句insert的列值,VALUES(name)表示的就是'bb'
結果顯示,影響行數2條
如上圖所示,addr欄位的值被保留了。
insert into on duplicate key update語句的做法是先插入記錄,如果不成功,則更新記錄,但是為什麼影響的行數是2?
我們重新建一張表test2
1 2 3 4 5 6 7 8 |
CREATE TABLE `test2` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID' ,
`sn` varchar(32) DEFAULT '' COMMENT '唯一鍵' ,
`name` varchar(32) DEFAULT '' COMMENT '姓名' ,
`addr` varchar(256) DEFAULT '' COMMENT '地址' ,
PRIMARY KEY (`id`),
UNIQUE KEY `sn` (`sn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
往裡面插入點資料
1 2 3 4 5 6 |
INSERT INTO test2
VALUES
(NULL, '01' , 'a' , 'aaa' ),
(NULL, '02' , 'b' , 'bbb' ),
(NULL, '03' , 'c' , 'ccc' ),
(NULL, '04' , 'd' , 'ddd' );
|
我們執行如下語句:
1 2 3 4 5 6 7 |
INSERT INTO test2 (sn, name, addr)
VALUES
( '02' , 'bb' , 'bbbb' )
ON DUPLICATE KEY
UPDATE
name = VALUES(name),
addr = VALUES(addr);
|
結果如下:
每執行一次上面的語句,雖然影響行數為0,但表test2的自增欄位就加1。
顯然如果insert into on duplicate key update語句僅僅只是在原記錄基礎上進行更新操作的話,自增欄位是不會自動加1的,說明它也進行了記錄刪除操作。
先插入記錄,如果不成功,則刪除原記錄,但保留了除update語句後欄位的值,然後把保留的值與需要更新的值合併,然後插入一條新記錄。
總結:
replace into 與 insert into on duplicate key update都是先嚐試插入記錄,如果不成功,則刪除記錄,replace into不保留原記錄的值,而insert into on duplicate key update保留。然後插入一條新記錄。