mysql 獲取全局唯一值


  在涉及數據庫存儲數據的時候,經常會遇到唯一值問題,有的是主鍵帶來的限制,有的則是業務上的需要。

  下面介紹幾種唯一值的獲取或者生產方法:

  先建一個測試用的表tbl_user,有三個字段:Id、Name、Age,其中Id為主鍵。
   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;
  查詢結果:
  image
 
  1.由 應用程序根據一定算法生成唯一值:一般采用” MD5(時間戳+隨機數)“或者其他的UUID算法,基本也比較好實現。如果遇到多機器上分布的程序訪問統一數據庫的表,可以把Ip、網卡號等信息考進來就可以解決了(當然可以不是簡單的拼接,你可以根據需要去合適的位數經過一定的算法去獲取)。
 

  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:   

  此時表中數據為

  image

  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;得到的當前表記錄為

  image

  過剛插入的數據“小猴”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;得到的所有記錄為

  image

  歡迎轉載,方便的話,請注明出處,謝謝

  作者:子韋一


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM