在涉及數據庫存儲數據的時候,經常會遇到唯一值問題,有的是主鍵帶來的限制,有的則是業務上的需要。
下面介紹幾種唯一值的獲取或者生產方法:
1: drop table if exists `tbl_user`;
2: create table
3: `tbl_user` (
4: `Id` int(10),
5: `Name` varchar(20),
6: `Age` int(10),
7: PRIMARY KEY (`Id`)
8: )DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
插入幾條數據
1: insert into tbl_user values (1000,"小貓",22);
2: insert into tbl_user values (1001,"小狗",22);
3: insert into tbl_user values (1002,"小刺蝟",22);
4:
5: select * from tbl_user;
查詢結果:
2.先查詢表中最大的值select max(id),再加1后作為新的值。很笨的方法。
1: select max(Id) from tbl_user;
2: 查詢到的最大Id為 1002
3:
4: 之后插入 1003
5:
6: insert into tbl_user values (1003,"小熊",22);
7:
此時表中數據為
3.如果是表級別的唯一,即在同一個表中某個字段唯一,可以把該字段設置為“自增(AUTO_INCREMENT)”的。這樣你不必費心思去生成這個不能重復的唯一值了。但是一般應用程序是需要這個唯一值的,這個時候你就得在查詢一次去獲取剛才數據庫自增生成的Id。比如在用戶登錄的時候,你要生成一個登錄會話Id或者Token,這些程序一般是需要得到這個值而不是僅僅存在數據庫中。生成的值,1.可以一般的select條件查詢,根據條件查詢剛才插入的數據。2.直接調用select @@IDENTITY 就可以得到上一次插入記錄時自動產生的ID(注意是在數據庫同一個連接(會話)中),用在插入后立即select @@IDENTITY 。
看例子,先將表中的Id字段設置為自增,再插入一條數據(不要插入Id值,讓數據庫自增得到值),select @@IDENTITY查詢,最后驗證看看。
1.#將Id改為自增(auto_increment) ALTER TABLE tbl_user CHANGE Id Id int not null auto_increment; #或者 先刪除Id字段再添加一個Id字段 alter table tbl_user auto_increment=1000; alter table tbl_user drop column Id; alter table tbl_user add Id int not null auto_increment primary key first; 2.插入一條記錄 insert tbl_user set Name='小猴',Age=23; 3.查詢剛才的自增Id值 select @@IDENTITY; 值是1004,
驗證下:select * from tbl_user;得到的當前表記錄為
過剛插入的數據“小猴”id為1004,和select @@IDENTITY;結果一樣。
4.使用mysql的 UUID()函數。前面的自增字段(auto_increment)只能生成”表內”的唯一值,且需要搭配使其為”唯一的主鍵或唯一索引”,它的值是逐步增長的。這里的UUID產生的是字符串類型值,固定長度為:36個字符。UUID生成的是在時間、空間上都獨一無二的值,是“隨機+規則”組合而成。
select uuid(); select uuid(); 執行兩次,結果: 69ad8b74-6d47-11e3-ba6e-7446a08ee8ec 69b03c16-6d47-11e3-ba6e-7446a08ee8ec
可以看到,多次調用UUID()函數得到的值不相同,它由五部分組成,並且有連字符(-)隔開,一共36個字符。其中:
前3組值是時間戳換算過來的,解決“時間上唯一”;
第4組值是暫時性保持時間戳的唯一性,重啟mysql才會變動;
第5組是mac值轉過來的,有助於解決“空間上的唯一”,同一個機器多實例的一般相同。如果mac值獲取不到,則是一個隨機值。
這些已經可以保證得到的值在時間和空間上的唯一。當然你也可以去掉連字符: select replace(uuid(),'-','')。
在MySQL 5.1.*及更高版本有一個變種的UUID()函數,UUID_SHORT(),可以生成一個17-64位無符號的整數,注意是生成的一個整數,而前面UUID()生成的是字符串。MySQL啟動后第一次執行的值是通過時間戳等初始化這個值,在本次運行中再次調用的時候都加1。這個值一般比較大,可以調用right(UUID_SHORT(),9)取后面的若干位。或者,你還可以寫成自定義函數,來按需生成這個值。舉個例子:
#1.調用uuid_short()函數 SELECT UUID_SHORT(); SELECT UUID_SHORT(); #執行兩次得到的值遞增的: 23285634974089216 23285634974089217 #2.創建一個自定義函數,按需獲取唯一值: CREATE DEFINER=`root`@`%` FUNCTION `GetUuidTest`(SysId int) RETURNS int(10) begin declare tmpID int; set tmpID = 0; #SELECT UUID_SHORT() into tmpID; #直接取值 SELECT concat(SysId,right(UUID_SHORT(),8)) into tmpID;#SysId和UUID_SHORT()后8位數拼接得到 return tmpID; end #3.調用自定義的函數GetUuidTest(int)函數: select GetUuidTest(1); select GetUuidTest(1); select GetUuidTest(2); select GetUuidTest(2); #得到結果: 174089233 #1+uuid_short()后8位(74089233)組成 174089234 #1+uuid_short()后8位(74089234)組成 274089235 #2+uuid_short()后8位(74089235)組成 274089236 #3+uuid_short()后8位(74089236)組成 #uuid_short()值遞增,前面在加一個Id,不同的服務器IdSysId不同。 #4.在例子中調用自定義函數GetUuidTest(int) 來插入記錄:這時候不需要把Id設置為自增了。 insert tbl_user set Id=GetUuidTest(1),Name='小熊貓',Age=22; insert tbl_user set Id=GetUuidTest(2),Name='小鴨子',Age=21;
例子中,select * from tbl_user;得到的所有記錄為
作者:子韋一




