如何優雅的向MySQL唯一索引列增加值

文章簡介

在日常開發中,我們會經常遇到某一張表中某列或者多列的值是唯一的,不能重複插入同一個值。遇到這樣的設計,我們一般會設置一個unique的索引。也就是在要求值不能是重複的列或者多列上添加一個唯一索引。例如,會執行這一條SQL語句:

alter table table_name add unique [index_name] (col_name(lenght))

或者

create unique index index_name on table_name(col_name(length))

這兩條語句都表示給表中創建一條唯一索引的字段。

當我們創建好唯一索引之後,如果給索引列插入了重複值之後,MySQL會報一個下列的錯誤信息。

insert into userinfo(nickname, openid) VALUE (ENCRYPT(RAND() * 1000), 'jf/IxWYA060PA');
-- 具體得錯誤信息。
Duplicate entry 'jf/IxWYA060PA' for key 'ixd_openid'

表示不能在索引ixd_openid列上重複插入值jf/IxWYA060PA

針對這種情況,我們在業務代碼中,可以直接根據改錯誤信息來做具體得處理。同時也可以讓MySQL層面對該情況做處理。下面針對該情況做一個實際案例的顏值。

表結構

首先我們創建一張userinfo表,表中結構如下:

CREATE TABLE `demo`.`userinfo`  (
`id` int(10) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT,
`nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`openid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `ixd_openid`(`openid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

方案實現

先查詢在插入

按照常規的邏輯,我們先查詢索引列的值是否存在,如果不存在則插入,存在則返回用戶信息。這種方式操作簡單,但是在併發情況下,就會存在問題。

-- 先執行查詢操作
select openid from userinfo where openid = 'jf/IxWYA060PA';
-- 如果MySQL返回空,表示數據不存在則執行插入操作
insert into userinfo(nickname, openid) VALUE (ENCRYPT(RAND() * 1000), 'jf/IxWYA060PA');

使用ignore

當我們重複插入數據時,MySQL會返回一個Duplicate entry xxx for xxx的信息,表示該列重複。適用ignore就會忽略該錯誤信息,只是MySQL不會做插入操作。

insert ignore into userinfo(nickname, openid) VALUE (ENCRYPT(RAND() * 1000), 'jf/IxWYA060PA');

增加ignore之後,出現重複插入的情況,MySQL會返回Affected rows: 0。只是插入的數據爲條數0,並且id內部也會自增,導致id的值不是連續的。此時我們增加一條不重複的數據,在來查詢數據表,就會發現id字段不是連續的。

on duplicate key update

使用該方式插入,當存在重複插入的情況下,MySQL同樣的不會返回重複插入的信息。

insert  into userinfo(nickname, openid) VALUE (ENCRYPT(RAND() * 1000), 'jf/IxWYA060PA') on duplicate key update openid = 'jf/IxWYA060PA';

此時MySQL會返回一個Affected rows: 0信息。只是插入的數據爲條數0,並且id內部也會自增,導致id的值不是連續的。

replace

使用該方式,會將原來存在的數據進行刪除,然後新增一條數據。

replace into userinfo(nickname, openid) value(ENCRYPT(RAND() * 1000), 'jf/IxWYA060PA');

此時MySQL會返回一個Affected rows: 2信息。這裏返回2。表示你1條數據被刪除的數據,另外新增1條數據。

推薦閱讀

Mysql百萬級數據遷移實戰筆記

徹底講明白MySQL的樂觀鎖和悲觀鎖

這一次終於有人把MySQL主從複製講全面了

開發人員必備的MySQL事務原理分析與總結



本文分享自微信公衆號 - 卡二條的技術圈(qq1005349393)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章