程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL批量拔出趕上獨一索引防止辦法

MySQL批量拔出趕上獨一索引防止辦法

編輯:MySQL綜合教程

MySQL批量拔出趕上獨一索引防止辦法。本站提示廣大學習愛好者:(MySQL批量拔出趕上獨一索引防止辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是MySQL批量拔出趕上獨一索引防止辦法正文


1、配景

之前應用SQL Server停止表分區的時刻就碰著許多關於獨一索引的成績:Step8:SQL Server 當表分區趕上獨一束縛,沒想到在MySQL的分區中一樣會碰到如許的成績:MySQL表分區實戰。

明天我們來懂得MySQL獨一索引的一些常識:包含若何創立,若何批量拔出,還有一些技能上SQL;

這些成績的本源在甚麼處所?有甚麼配合點?MySQL中也有分區對齊的概念?獨一索引是在許多體系中都邑湧現的請求,有甚麼方法可以免?它對機能的影響有多年夜?

2、進程

(一) 導入差別數據,疏忽反復數據,IGNORE INTO的應用

在MySQL創立表的時刻,我們平日創立一個表的時刻是以一個自增ID值作為主鍵,那末MySQL就會以PRIMARY KEY作為集合索引鍵和主鍵,既然是主鍵,那固然是獨一的了,所以反復履行上面的拔出語句會報1062毛病:如Figure1所示;

-- 創立測試表
CREATE TABLE `testtable` (
`Id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`UserId` INT(11) DEFAULT NULL,
`UserName` VARCHAR(10) DEFAULT NULL,
`UserType` INT(11) DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

-- 拔出測試數據
INSERT INTO testtable(Id,UserId,UserName,UserType)
VALUES(1,101,'aa',1),(2,102,'bbb',2),(3,103,'ccc',3);

u1_1062

(Figure1:Duplicate entry '1' for key 'PRIMARY')

然則在現實的臨盆情況中,需求常常是須要在UserId鍵值中設置獨一索引,明天我就以這個作為示例,停止獨一索引的測試:

-- 創立測試表1
CREATE TABLE `testtable1` (
`Id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`UserId` INT(11) DEFAULT NULL,
`UserName` VARCHAR(10) DEFAULT NULL,
`UserType` INT(11) DEFAULT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `IX_UserId` (`UserId`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

-- 創立測試表2
CREATE TABLE `testtable2` (
`Id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`UserId` INT(11) DEFAULT NULL,
`UserName` VARCHAR(10) DEFAULT NULL,
`UserType` INT(11) DEFAULT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `IX_UserId` (`UserId`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

-- 拔出測試數據1
INSERT INTO testtable1(Id,UserId,UserName,UserType)
VALUES(1,101,'aa',1),(2,102,'bbb',2),(3,103,'ccc',3);

-- 拔出測試數據2
INSERT INTO testtable2(Id,UserId,UserName,UserType)
VALUES(1,201,'aaa',1),(2,202,'bbb',2),(3,203,'ccc',3),(4,101,'xxxx',5);

u2_table1

(Figure2:testtable1記載)

u3_table2

(Figure3:testtable2記載)

經由過程履行下面的SQL劇本,我們在testtable1和testtable2都創立了獨一索引:UNIQUE KEY `IX_UserId` (`UserId`),這就解釋UserId在testtable1和testtable2表中都是獨一的,假如把testtable2的數據批量導入到testtable1,假如履行上面【導入1】的SQL,就會湧現1062的毛病,招致全部進程會回滾,沒有到達導入差別數據的目標。

INSERT INTO testtable1(UserId,UserName,UserType)
SELECT UserId,UserName,UserType FROM testtable2;

u4_unique

(Figure4:Duplicate entry '101' for key 'IX_UserId')

MySQL供給一個症結字:IGNORE,這個症結字斷定每筆記錄能否存在,能否違背餓了表中的獨一索引,假如存在就不拔出,而不存在的記載就會拔出。

-- 導入2
INSERT IGNORE INTO testtable1(UserId,UserName,UserType)
SELECT UserId,UserName,UserType FROM testtable2;

所以履行完【導入2】,就會發生Figure5的成果,這曾經到達了我們的目標了,然則你有沒發明自增的ID值跳過了一些值,這是由於我們之前履行【導入1】掉敗形成的,固然我們的事務回滾了,然則自增ID會湧現斷層。在SQL Server中也會有如許的成績。擴大浏覽:簡略適用SQL劇本Part:查找SQL Server 自增ID值不持續記載

u5_效果

(Figure5:IGNORE後果)

(二) 導入並籠罩反復數據,REPLACE INTO 的應用

1. 把testtable1和testtable2分離回滾到Figure2和Figure3的狀況(應用TRUNCATE TABLE定名再履行Insert語句),這個時刻再履行上面的SQL,看有甚麼後果:

-- 導入3
REPLACE INTO testtable1(UserId,UserName)
SELECT UserId,UserName FROM testtable2;

u6_rep

(Figure6:REPLACE後果)

從上圖Figure6中,我們可以看到:UserId為101的記載產生了轉變,不單UserName修正了,並且UserType也變成NULL了。

所以,假如導入中發明了反復的,先刪除再拔出,假如記載有多個字段,在拔出的時刻假如有的字段沒有賦值,那末新拔出的記載這些字段為空(新拔出記載的UserType都為NULL)。

須要留意的是,當你replace的時刻,假如被拔出的表假如沒有指定列,會用NULL表現,而不是這個表本來的內容。假如拔出的內容列和被拔出的表列一樣,則不會湧現NULL。

2. 假如我們表構造UserType字段不許可為空,並且沒有默許值的情形,履行【導入3】會產生甚麼工作呢?

u7_not null

(Figure7:前往正告信息)

u8_0

(Figure8:UserType被設置為0)

經由過程Figure7和Figure8,我們曉得數據記載照樣拔出了,只是前往Field 'UserType' doesn't have a default value的正告,拔出記載的UserType字段都被設置為0('UserType' 為int數據類型)。

3. 假如我們願望導入的時刻一路更新UserType字段的值,這天然很簡略了,應用上面的SQL劇本便可以處理:

-- 導入4
REPLACE INTO testtable1(UserId,UserName,UserType)
SELECT UserId,UserName,UserType FROM testtable2;

u9_rep

(Figure9:一路更新UserType)

(三) 導入保存反復數據未指定字段,INSERT INTO ON DUPLICATE KEY UPDATE 的應用

把testtable1和testtable2分離回滾到Figure2和Figure3的狀況(應用TRUNCATE TABLE定名再履行Insert語句),這個時刻再履行上面的SQL,看有甚麼後果:

-- 導入5
INSERT INTO testtable1(UserId,UserName)
SELECT UserId,UserName FROM testtable2
ON DUPLICATE KEY UPDATE
testtable1.UserName = testtable2.UserName;

u10_update

(Figure10:保存UserType值)

比較Figure2、Figure3與Figure10,UserId為101的記載:更新了UserName的值,保存了UserType的值;然則因為【導入5】中沒有指定UserType,所以新拔出記載的UserType是為NULL的。

-- 導入6
INSERT INTO testtable1(UserId,UserName,UserType)
SELECT UserId,UserName,UserType FROM testtable2
ON DUPLICATE KEY UPDATE
testtable1.UserName = testtable2.UserName;

u11_update

(Figure11:保存UserType值)

比較Figure2、Figure3與Figure11,只拔出testtable2表的UserId,UserName字段,然則保存testtable1表的UserType字段。假如發明有反復的記載,做更新操作;在原有記載基本上,更新指定字段內容,其它字段內容保存。

(四) 總結

當在一個UNIQUE鍵上拔出包括反復值的記載時,默許的insert會報1062毛病,MYSQL可以經由過程以上三種分歧的方法和你的營業邏輯停止處置。

3、參考文獻

MYSQL拔出處置反復鍵值的幾種辦法

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved