bitscn.com
在涉及数据库存储数据的时候,经常会遇到唯一值问题,有的是主键带来的限制,有的则是业务上的需要。
下面介绍几种唯一值的获取或者生产方法:
先建一个测试用的表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;
查询结果:
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:
此时表中数据为
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-7446a08ee8ec69b03c16-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();#执行两次得到的值递增的:2328563497408921623285634974089217#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;得到的所有记录为
欢迎转载,方便的话,请注明出处,谢谢!
作者:子韦一
bitscn.com