我有两个表:category(cat_id type int,cat_name)
和books(book_id type int,cat_id)
。当我将一本书分配给用户时,他将获得一个book code
。我想形成这个包含12个字母数字字符的书码,它必须起源于cat_id
和book_id
。此外,我应该能够解码代码以获得cat_id
和book_id
。任何主意?。
有一个更简单的方法是使用HEX,但是你需要决定用多少数字来表示图书,用多少数字来表示类别。
例如,我建议用8表示书,用4表示类别,如下所示。通过使用十六进制1,最大记录是FFFFFFFF FFFF,在这里您可以用完所有的unsigned int for books (max。4294967295本书)和65535类
实际上,LPAD(HEX(book_id), 8, '0')
表示前8位数字,LPAD(HEX(cat_id), 4, '0')
表示后4位数字。
所以你想要的图书代码可以通过SELECT CONCAT(LPAD(HEX(book_id), 8, '0'),LPAD(HEX(cat_id), 4, '0')) FROM books
检索回:SELECT UNHEX(substr(code,1,8)) as book_id, UNHEX(substr(code,9,4)) as cat_id FROM bookcode WHERE id=1
如果您希望在图书代码中包含更大的数据集,您可以尝试对这两项使用base36甚至base62(区分大小写)编码。这种编码需要您自己的用户程序代码。
好了…
this可以处理最大有符号整数类型。并且产生不超过12个字符。
$firstId = "2147483646";
$secondId = "2147483646";
$firstBinary = str_pad(base_convert($firstId, 10, 2), 31, "0", STR_PAD_LEFT);
$secondBinary = str_pad(base_convert($secondId, 10, 2), 31, "0", STR_PAD_LEFT);
$finalBase36 = str_pad(base_convert($firstBinary.$secondBinary, 2, 36), 12, "0", STR_PAD_LEFT);
var_dump($finalBase36);
更新:对不起,我犯了一个错误。这应该与更新后的代码相同。
假设int
类型为32位无符号整数。2个int
组合起来将有2^64个唯一值,大约是1.844e19。
如果我们只使用小写或大写英文字母,加上数字,那么有36^12 = 4.738e18个不同的值,这不足以创建从2个键到书码的一对一映射。
如果在图书代码字符集中再添加5个字符,将会有41^12 = 2.256e19个不同的值,这足以创建一对一的映射。
但是,转换将涉及除法和乘法,在从图书代码转换回键时可能会发生整数溢出。
如果可能的话,您可能希望将字符集扩展到64个字符:26 * 2小写/大写英文字母,10位数字和2个特殊字符(可能是_
或-
),在那里您可以使用位移位-这是安全的整数溢出。对于未使用的位,您可能希望用随机数据填充它,这是由2个键播种的;反向构造将忽略具有随机位的(固定)位置。