這個(gè)例子其實(shí)是非常的簡(jiǎn)單了就是要實(shí)現(xiàn)sql插入數(shù)據(jù)時(shí),如果已經(jīng)存在,則執(zhí)行update更新了,這樣對(duì)于sql與程序來(lái)講是非常的簡(jiǎn)潔的,下面就和小編一起來(lái)深入的分析一下吧.
在很多項(xiàng)目中,我們需要對(duì)數(shù)據(jù)進(jìn)行不斷的調(diào)用和更新,如果有新的數(shù)據(jù)過(guò)來(lái),還要把它加入到數(shù)據(jù)庫(kù)中。其中非常重要的一種情況就是,我們不知道傳過(guò)來(lái)的數(shù)據(jù)是不是原本數(shù)據(jù)庫(kù)中就已經(jīng)有了的記錄,所以我們常常需要先通過(guò)抓取數(shù)據(jù),判斷是否存在,如果存在執(zhí)行update,如果不存在執(zhí)行insert,這樣就要進(jìn)行兩次數(shù)據(jù)庫(kù)操作,第一次是查詢(xún),第二次是更新或插入,有沒(méi)有一種方法可以只需要執(zhí)行一次操作即可呢?答案是有的。
INSERT ... ON DUPLICATE KEY UPDATE 方法可以幫助我們非常好的解決這一問(wèn)題。讓我們來(lái)看一個(gè)例子:
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE b=b-1,c=c+1;
這一個(gè)語(yǔ)句就可以實(shí)現(xiàn),在插入(1,2,3)這條記錄的時(shí)候,檢查是否存在a=1,如果有a=1的記錄,那么更新a=1這條記錄,相當(dāng)于執(zhí)行了一次下面這個(gè)語(yǔ)句:
UPDATE table SET b=b-1,c=c+1 WHERE a=1;
如果數(shù)據(jù)庫(kù)中不存在a=1這條記錄,那么就插入新的記錄.
使用INSERT ... ON DUPLICATE KEY UPDATE的前提是,a字段被設(shè)置為“唯一鍵”索引,否則該方法是無(wú)效的.
再看一些例子:
該語(yǔ)句是基于唯一索引或主鍵使用,比如一個(gè)字段a被加上了unique index,并且表中已經(jīng)存在了一條記錄值為1,下面兩個(gè)語(yǔ)句會(huì)有相同的效果:
- INSERT INTO table (a,b,c) VALUES (1,2,3)
- ON DUPLICATE KEY UPDATE c=c+1;
- UPDATE table SET c=c+1 WHERE a=1;
ON DUPLICATE KEY UPDATE后面可以放多個(gè)字段,用英文逗號(hào)分割,使用ON DUPLICATE KEY UPDATE,最終如果插入了一個(gè)新行,則受影響的行數(shù)是1,如果修改了已存在的一行數(shù)據(jù),則受影響的行數(shù)是2.
如果字段b也被加上了unique index,則該語(yǔ)句和下面的update語(yǔ)句是等效的:
UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
如果a=1 OR b=2匹配了多行,則只有一行會(huì)被修改。通常的,在ON DUPLICATE KEY UPDATE語(yǔ)句中,我們應(yīng)該避免多個(gè)唯一索引的情況。如果需要插入或更新多條數(shù)據(jù),并且更新的字段需要根據(jù)其它字段來(lái)運(yùn)算時(shí),可以使用如下語(yǔ)句:
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
在ON DUPLICATE KEY UPDATE后面使用VALUES()方法,這個(gè)語(yǔ)句等同于下面的兩個(gè)語(yǔ)句:
- INSERT INTO table (a,b,c) VALUES (1,2,3)
- ON DUPLICATE KEY UPDATE c=3;--1+2
- INSERT INTO table (a,b,c) VALUES (4,5,6)
- ON DUPLICATE KEY UPDATE c=9;--4+5
- --Vevb.com
如果一個(gè)表中包含了一個(gè)auto_increment的字段,每次insert數(shù)據(jù)后,可以通過(guò)last_insert_id()方法返回最后自動(dòng)生成的值,如果通過(guò)INSERT ... ON DUPLICATE KEY UPDATE語(yǔ)句修改了一條數(shù)據(jù),那么再通過(guò)last_insert_id()方法獲取的值將不正確,實(shí)際測(cè)試中是多了一個(gè)數(shù),比如向表中增加了3條數(shù)據(jù),那么通過(guò)last_insert_id()方法得到的值是3,但是通過(guò)該語(yǔ)句修改了一條數(shù)據(jù)后,通過(guò)last_insert_id()方法得到的值是4。如果想解決該問(wèn)題,可以通過(guò)如下語(yǔ)句:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
重點(diǎn)是這句id=LAST_INSERT_ID(id),還有一種方法是使用ignore,我們來(lái)看一個(gè)例子:
INSERT ignore INTO a(id, type) VALUES ( 11, 22)
這個(gè)語(yǔ)句中使用了ignore,意思是:如果數(shù)據(jù)庫(kù)中存在一條記錄id=11,那么就不執(zhí)行insert操作(忽略),只有上述條件不滿(mǎn)足時(shí)才執(zhí)行插入操作,ignore方法也要求這里的id為唯一鍵(主鍵默認(rèn)就是是唯一鍵,因此id可以是主鍵).
另外,還有一種方法是replace into,它的使用方法和insert into一樣,但是和上面的ignore效果不同,如果數(shù)據(jù)庫(kù)中已經(jīng)存在id=11,那么強(qiáng)制替換id=11這條記錄的type為22.
看個(gè)例子:下面通過(guò)代碼說(shuō)明之間的區(qū)別,如下:
- create table testtb(
- id int not null primary key,
- name varchar(50),
- age int
- );
- insert into testtb(id,name,age)values(1,"bb",13);
- select * from testtb;
- insert ignore into testtb(id,name,age)values(1,"aa",13);
- select * from testtb;//仍是1,“bb”,13,因?yàn)閕d是主鍵,出現(xiàn)主鍵重復(fù)但使用了ignore則錯(cuò)誤被忽略
- replace into testtb(id,name,age)values(1,"aa",12);
- select * from testtb; //數(shù)據(jù)變?yōu)?,"aa",12
總結(jié)一下:如果要實(shí)現(xiàn)插入數(shù)據(jù)時(shí)檢查是否已經(jīng)存在某個(gè)唯一鍵的數(shù)據(jù),如果存在,則替換該記錄的其他字段,我們可以使用三種方法來(lái)實(shí)現(xiàn)插入數(shù)據(jù)時(shí)判斷是否存在對(duì)應(yīng)鍵的記錄,分別是INSERT ... ON DUPLICATE KEY UPDATE、insert gnore into和replace into,其中INSERT ... ON DUPLICATE KEY UPDATE和replace into可以實(shí)現(xiàn)如果已經(jīng)存在對(duì)應(yīng)鍵的記錄時(shí),替換該記錄的其他字段.
新聞熱點(diǎn)
疑難解答
圖片精選