前言
演示MySQL中,插入或替換、插入或更新、插入或忽略等語句的用法。
數據準備
創建一個空表作爲演示,其中字段id
爲主鍵,字段num
爲唯一索引
CREATE TABLE student (
id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
num varchar(20) NOT NULL COMMENT '學生學號',
name varchar(20) NOT NULL COMMENT '學生姓名',
PRIMARY KEY (id),
UNIQUE KEY uk_num (num) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入或替換
執行算法
嘗試往表插入一條記錄,如果記錄不存在,則直接插入(insert);如果記錄已存在,則先刪除原記錄,再插入(delete + insert)。
判斷記錄存在與否,是根據表的PRIMARY KEY
或者UNIQUE index
實例演示
執行replace
語句,由於表中還沒任何記錄,所以插入的記錄肯定在表中不存在。數據庫直接插入記錄,受影響行數爲1
replace into student(id, num, name) values (1, '1001', '張三');
此時表所有記錄如下圖所示
繼續執行另一個replace
語句,由於字段num
爲唯一索引,嘗試插入的記錄的num
值也是1001
,所以表中其實已存在了重複的記錄。數據庫先把判斷爲重複的記錄刪除,再插入新記錄,受影響行數爲2
replace into student(id, num, name) values(2, '1001', '李四');
此時表所有記錄如下圖所示
插入或更新
執行算法
嘗試往表插入一條記錄,如果記錄不存在,則直接插入(insert);如果記錄已存在,則更新該記錄,更新的字段由
ON DUPLICATE KEY UPDATE
子句中的UPDATE
指定。
判斷記錄存在與否,是根據表的PRIMARY KEY
或者UNIQUE index
實例演示
爲方便查看,這裏先清除表所有記錄
delete from student;
執行insert
語句,帶上on duplicate key update
子句,由於表中暫時無記錄,不會造成“記錄存在”的情況,數據庫直接插入記錄,受影響行數爲1
insert into student(id, num, name) values (1, '1001', '張三') on duplicate key update name = '李四';
此時表所有記錄如下圖所示
繼續執行剛剛的insert
語句,由於嘗試插入的記錄無論根據主鍵id
字段,還是唯一索引num
字段,都是表中已存在的記錄,所以數據庫根據update
指定的字段,更新記錄的name
爲“李四”,受影響行數爲2(爲啥是2,請繼續往下看)
insert into student(id, num, name) values (1, '1001', '張三') on duplicate key update name = '李四';
此時表所有記錄如下圖所示
繼續第三次執行剛剛的insert
語句,此時數據庫受影響行數爲0,差不多相當於數據庫並沒有執行這個語句,其對數據庫記錄不造成任何改變。
insert into student(id, num, name) values (1, '1001', '張三') on duplicate key update name = '李四';
根據MySQL官網5.7版本的相關介紹
With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values.
可知執行插入或更新語句時,如果原先記錄不存在,那麼插入新記錄,受影響行數是1,這容易理解。但如果原先記錄存在,執行更新操作時,則分兩種情況:一種是update
指定的更新字段的值跟原先記錄的不一樣,則受影響行數是2,另一種是update
指定的更新字段的值跟原先記錄的一模一樣,則受影響行數是0
插入或忽略
執行算法
嘗試往表插入一條記錄,如果記錄不存在,則直接插入(insert);如果記錄已存在,則直接忽略,啥事也不幹。
判斷記錄存在與否,是根據表的PRIMARY KEY
或者UNIQUE index
實例演示
類似地,爲方便查看,這裏先清除表所有記錄
delete from student;
執行下面insert
語句,跟普通的insert
語句差不多,只是多了一個修飾語ignore
insert ignore into student(id, num, name) values (1, '1001', '張三');
此時表所有記錄如下圖所示
繼續執行剛剛的insert
語句,由於表中已存在對應記錄,故數據庫不執行任何操作,受影響行數爲0
insert ignore into student(id, num, name) values (1, '1001', '張三');
如果將ignore
修飾符去掉,執行相應insert
語句,數據庫報錯,操作被中斷。
insert into student(id, num, name) values (1, '1001', '張三');
總結
執行操作 | SQL語法 | 記錄不存在 | 記錄存在 | 說明 |
---|---|---|---|---|
插入或替換 | replace 語句 | insert | delete + insert | MySQL對標準SQL的一個擴展 |
插入或更新 | insert 語句 | insert | update | MySQL insert 語句的一個子句 |
插入或忽略 | insert 語句 | insert | 空操作 | MySQL insert 語句的一個修飾符 |
參考資料
- MySQL 5.7 Reference Manual 13.2.8 REPLACE Statement
- MySQL 5.7 Reference Manual 13.2.5 INSERT Statement
- MySQL 5.7 Reference Manual 13.2.5.2 INSERT … ON DUPLICATE KEY UPDATE Statement