我們日常使用 insert into 語句向表中插入數據時,一定遇到過主鍵或唯一索引沖突的情況,MySQL的反應是報錯并停止執行后續的語句,而replace into語句可以實現強制插入。
文章目錄
- 一、replace into 語句簡介
- 1.1 基本用法
- 1.2 使用set語句
- 二、注意事項
- 2.1 替換時必須要有主鍵或唯一索引
- 2.2 替換時無法引用舊行的數據
一、replace into 語句簡介
insert into語句在插入數據時如果遇到主鍵或唯一鍵沖突時,其反應是報錯并返回。而如果你想強制插入,即遇到鍵值沖突時使用最新的數據替換原數據,則可以用replace into來代替insert into語句。
1.1 基本用法
先創建一張測試表,并插入2條數據:
create table mytab(
id int not null auto_increment primary key,
source varchar(16),
value int default 999);insert into mytab values(1, 'insert', 100),(2,'insert', 200);
table mytab;
下面用insert into語句插入2條數據,這里主鍵id=2出現了沖突,語句會執行失敗:
insert into mytab values(2, 'insert', 200), (3, 'insert', 300);
table mytab;
將insert關鍵字替換為replace,當出現主鍵或唯一鍵沖突時,MySQL會先將表中沖突的數據刪除,然后再插入,即隱式的幫你做了一個delete操作:
replace into mytab values(2, 'replace', 200), (3, 'replace', 300);
table mytab;
這里插入了2行數據,但是返回結果顯示 3 rows affected,即是刪除了1行,插入2行,共影響3行數據。同時Duplicates:1,顯示有1行數據出現了重復。
1.2 使用set語句
replace into 還可以set語句用來指定每個列的值,這里更新id為1的行:
replace into mytab set id=1, source='set', value=101;
table mytab;
對于set中未指定的列,會被替換為默認值(這里不指定value的值,則其被設置成默認值999):
replace into mytab set id=1, source='set';
table mytab;
二、注意事項
2.1 替換時必須要有主鍵或唯一索引
replace into 發生替換時必須要檢測到主鍵或唯一索引沖突,否則它的行為就和普通的insert into相同,我想把id為1的行value值設置為100,但僅引用source列,而通過source列無法判定沖突:
replace into mytab set source='set', value=100;
table mytab;
所以最終語句并沒有像我預想的那樣發生替換,而是插入了一行新數據。
2.2 替換時無法引用舊行的數據
如果我想在發生沖突時在原數據的基礎上進行更新,這種場景replace into語句是無法做到的,因為在插入發生之前舊數據已經被刪除了,所以是無法引用舊數據的,這里嘗試將id=2的數據value值+1:
replace into mytab set id=2, source='plus 1', value=value+1;
table mytab;
可以看到最終結果并不是預想的201,而是1000。這是因為value=value+1,運算時無法引用舊值,而是引用了默認值。如果想實現沖突時在原數據上更新的效果,可以通過insert into … on duplcate key update語句實現。
最后提一句,replace into語句是MySQL對標準SQL的擴展,在其他RDBMS中可能并不適用。