在涉及数据库存储数据的时候,经常会遇到唯一值问题,有的是主键带来的限制,有的则是业务上的需要。

  下面介绍几种唯一值的获取或者生产方法:

  先建一个测试用的表tbl_user,有三个字段:Id、Name、Age,其中Id为主键。
  1. 1: drop table if exists `tbl_user`;
  1. 2: create table
  1. 3: `tbl_user` (
  1. 4: `Id` int(10),
  1. 5: `Name` varchar(20),
  1. 6: `Age` int(10),
  1. 7: PRIMARY KEY (`Id`)
  1. 8: )DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
  1.  

  插入几条数据

  1. 1: insert into tbl_user values (1000,"小猫",22);
  1. 2: insert into tbl_user values (1001,"小狗",22);
  1. 3: insert into tbl_user values (1002,"小刺猬",22);
  1. 4:  
  1. 5: select * from tbl_user;
  1.   查询结果:
  1.   
  1.  

  1.由应用程序根据一定算法生成唯一值:一般采用”MD5(时间戳+随机数)“或者其他的UUID算法,基本也比较好实现。如果遇到多机器上分布的程序访问统一数据库的表,可以把Ip、网卡号等信息考进来就可以解决了(当然可以不是简单的拼接,你可以根据需要去合适的位数经过一定的算法去获取)。
 

  2.先查询表中最大的值select max(id),再加1后作为新的值。很笨的方法。

  1. 1: select max(Id) from tbl_user;
  1. 2: 查询到的最大Id 1002
  1. 3:  
  1. 4: 之后插入 1003
  1. 5:  
  1. 6: insert into tbl_user values (1003,"小熊",22);
  1. 7:  

  此时表中数据为

  

  3.如果是表级别的唯一,即在同一个表中某个字段唯一,可以把该字段设置为“自增(AUTO_INCREMENT)”的。这样你不必费心思去生成这个不能重复的唯一值了。但是一般应用程序是需要这个唯一值的,这个时候你就得在查询一次去获取刚才数据库自增生成的Id。比如在用户登录的时候,你要生成一个登录会话Id或者Token,这些程序一般是需要得到这个值而不是仅仅存在数据库中。生成的值,1.可以一般的select条件查询,根据条件查询刚才插入的数据。2.直接调用select @@IDENTITY 就可以得到上一次插入记录时自动产生的ID(注意是在数据库同一个连接(会话)中),用在插入后立即select @@IDENTITY 。

  看例子,先将表中的Id字段设置为自增,再插入一条数据(不要插入Id值,让数据库自增得到值),select @@IDENTITY查询,最后验证看看。

  1. 1.#将Id改为自增(auto_increment)
  2. ALTER TABLE tbl_user CHANGE Id Id int not null auto_increment;
  3.  
  4. #或者 先删除Id字段再添加一个Id字段
  5. alter table tbl_user auto_increment=1000;
  6. alter table tbl_user drop column Id;
  7. alter table tbl_user add Id int not null auto_increment primary key first;
  8.  
  9. 2.插入一条记录
  10. insert tbl_user set Name='小猴',Age=23;
  11.  
  12. 3.查询刚才的自增Id
  13. select @@IDENTITY;
  14. 值是1004

  验证下:select * from tbl_user;得到的当前表记录为

  

  过刚插入的数据“小猴”id为1004,和select @@IDENTITY;结果一样。

  4.使用mysql的 UUID()函数。前面的自增字段(auto_increment)只能生成”表内”的唯一值,且需要搭配使其为”唯一的主键或唯一索引”,它的值是逐步增长的。这里的UUID产生的是字符串类型值,固定长度为:36个字符。UUID生成的是在时间、空间上都独一无二的值,是“随机+规则”组合而成。

  1. select uuid();
  2. select uuid();
  3.  
  4. 执行两次,结果:
  5. 69ad8b74-6d47-11e3-ba6e-7446a08ee8ec
  6. 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. #1.调用uuid_short()函数
  2. SELECT UUID_SHORT();
  3. SELECT UUID_SHORT();
  4.  
  5. #执行两次得到的值递增的:
  6. 23285634974089216
  7. 23285634974089217
  8.  
  9. #2.创建一个自定义函数,按需获取唯一值:
  10. CREATE DEFINER=`root`@`%` FUNCTION `GetUuidTest`(SysId int) RETURNS int(10)
  11. begin
  12. declare tmpID int;
  13. set tmpID = 0;
  14. #SELECT UUID_SHORT() into tmpID; #直接取值
  15. SELECT concat(SysId,right(UUID_SHORT(),8)) into tmpID;#SysIdUUID_SHORT()后8位数拼接得到
  16. return tmpID;
  17. end
  18.  
  19. #3.调用自定义的函数GetUuidTest(int)函数:
  20. select GetUuidTest(1);
  21. select GetUuidTest(1);
  22. select GetUuidTest(2);
  23. select GetUuidTest(2);
  24. #得到结果:
  25. 174089233 #1+uuid_short()后8位(74089233)组成
  26. 174089234 #1+uuid_short()后8位(74089234)组成
  27. 274089235 #2+uuid_short()后8位(74089235)组成
  28. 274089236 #3+uuid_short()后8位(74089236)组成
  29. #uuid_short()值递增,前面在加一个Id,不同的服务器IdSysId不同。
  30.  
  31. #4.在例子中调用自定义函数GetUuidTest(int) 来插入记录:这时候不需要把Id设置为自增了。
  32. insert tbl_user set Id=GetUuidTest(1),Name='小熊猫',Age=22;
  33. insert tbl_user set Id=GetUuidTest(2),Name='小鸭子',Age=21;

  例子中,select * from tbl_user;得到的所有记录为

  

  欢迎转载,方便的话,请注明出处,谢谢

  作者:子韦一

mysql 获取全局唯一值的更多相关文章

  1. 获取字段唯一值工具- -ArcPy和Python案例学习笔记

    获取字段唯一值工具- -ArcPy和Python案例学习笔记   目的:获取某一字段的唯一值,可以作为工具使用,也可以作为函数调用 联系方式:谢老师,135-4855-4328,xiexiaokui# ...

  2. 高并发分布式环境中获取全局唯一ID[分布式数据库全局唯一主键生成]

    需求说明 在过去单机系统中,生成唯一ID比较简单,可以使用MySQL的自增主键或者Oracle中的sequence, 在现在的大型高并发分布式系统中,以上策略就会有问题了,因为不同的数据库会部署到不同 ...

  3. iOS 获取全局唯一标示符

    这个方法用来产生一个唯一的标示符,每次调用都会不一样,所以可以用当作一些临时缓存文件的名字 NSString *identifier = [[NSProcessInfo processInfo] gl ...

  4. 如何在高并发分布式系统中生成全局唯一Id

    月整理出来,有兴趣的园友可以关注下我的博客. 分享原由,最近公司用到,并且在找最合适的方案,希望大家多参与讨论和提出新方案.我和我的小伙伴们也讨论了这个主题,我受益匪浅啊…… 博文示例: 1.     ...

  5. 如何在高并发分布式系统中生成全局唯一Id(转)

    http://www.cnblogs.com/heyuquan/p/global-guid-identity-maxId.html 又一个多月没冒泡了,其实最近学了些东西,但是没有安排时间整理成博文, ...

  6. (转)如何在高并发分布式系统中生成全局唯一Id

    又一个多月没冒泡了,其实最近学了些东西,但是没有安排时间整理成博文,后续再奉上.最近还写了一个发邮件的组件以及性能测试请看 <NET开发邮件发送功能的全面教程(含邮件组件源码)> ,还弄了 ...

  7. 生成全局唯一ID

    在实际业务处理中,有时需要生成全局唯一ID来区别同类型的不同事物,介绍一下几种方式及其C++实现 //获取全局唯一ID //server_id为服务的id,因当同一个服务部署在多个服务器上时,需要区别 ...

  8. SnowFlake 生成全局唯一id

    public class SnowFlakeUtil { private long workerId; private long datacenterId; private long sequence ...

  9. Mysql系列七:分库分表技术难题之分布式全局唯一id解决方案

    一.前言 在前面的文章Mysql系列四:数据库分库分表基础理论中,已经说过分库分表需要应对的技术难题有如下几个: 1. 分布式全局唯一id 2. 分片规则和策略 3. 跨分片技术问题 4. 跨分片事物 ...

随机推荐

  1. 【android】java.net.ConnectException: localhost/127.0.0.1:8080 - Connection refused

    调试中通过android simulator模拟器链接localhost或者127.0.0.1,因为我在电脑上面建立了apache,我的代码大概就是URL url = new URL(urlStrin ...

  2. Cut the sticks

    def main(): n = int(raw_input()) arr = map(int, raw_input().strip().split()) for i in range(n): cutN ...

  3. js 非IE火狐插件检测

    js检测代码Html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:// ...

  4. ByteArrayOutputStream的用法

    ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区,然后利用ByteArrayOutputStream和ByteArrayInputStream的 ...

  5. block(三)揭开神秘面纱(上)

    block到底是什么 我们使用clang的rewrite-objc命令来获取转码后的代码. 1.block的底层实现 我们来看看最简单的一个block: [caption id="attac ...

  6. 执行yiic webapp命令时报错:php.exe不是内部或外部命令,也不是可运行的程序

    在执行 yiic webapp ../abc 命令时报错: “php.exe”不是内部或外部命令,也不是可运行的程序 或批处理文件. 这是因为yiic批处理程序找不到php.exe的执行路径引起的. ...

  7. mysql 导出导入sql

    >mysqldump -u用户名 -p密码 -h主机名 数据库名 > 20150116mw_pm_db.sql mysql> source /home/y/my_work/20150 ...

  8. 阻碍android程序员发展的几个原因

    1应该少看网上的android开发相关技术帖子,一个是错误很多,表达也不清楚,很多都是拷贝来拷贝去的.二个是技术变迁快,很多都过时了,经常看android技术相关帖子,养成了一种惰性,遇到问题不是去看 ...

  9. Increasing/ Decreasing Stack

    对于此类问题: 对于元素nums[i],找出往左/右走第一个比它小/大的数字 我们常常用递增栈/递减栈实现. 递增栈实现第一个比它小 递减栈实现第一个比它大 Example: 2 1 5 6 2 3 ...

  10. Java日志终极指南

    Java日志基础 Java使用了一种自定义的.可扩展的方法来输出日志.虽然Java通过java.util.logging包提供了一套基本的日志处理API,但你可以很轻松的使用一种或者多种其它日志解决方 ...