PHP/MySQL:存储和检索UUID

12

我正在尝试向几个表添加UUID,但我不确定最好的存储/检索方式是什么。我了解到使用BINARY(16)而不是VARCHAR(36)要更有效率。经过一番研究,我还发现可以使用以下方式将UUID字符串转换为二进制:

 UNHEX(REPLACE(UUID(),'-',''))

请原谅我的无知,但是是否有一种简单的方法可以使用PHP来实现这个功能,然后在需要时将其转换回字符串以便于阅读?

另外,如果我将其用作主键而不是auto_increment,会有很大的区别吗?

编辑:

找到了部分答案:

 $bin = pack("h*", str_replace('-', '', $guid));

你如何解压它?


1
https://dev59.com/DHRB5IYBdhLWcg3wtJGF - zs2020
1
http://php.net/manual/en/function.unpack.php - Amber
3个回答

14

好的 - 我将尝试回答自己的问题。这是我能想到的最好解决方案:

打包:

$binary =  pack("h*", str_replace('-', '', $string));
解包
$string = unpack("h*", $binary);
$string = preg_replace("/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/", "$1-$2-$3-$4-$5", $string);

有人能看出这个代码存在什么问题吗?


1
注意,unpack方法返回一个数组: $arr = unpack("h*", $binUUID); $string = $arr['1']; - ıɾuǝʞ
7
如果您想与MySQL的(UN)HEX函数兼容,那么这是错误的使用pack函数的方式。您需要使用pack('H*')(大写的H)。 - Johan B.W. de Vries

9

正如@Johan所提到的那样,您需要使用大写H(十六进制字符串,高位在前)以便与MySQL HEX / UNHEX函数兼容。

function uuid_to_bin($uuid){
  return pack("H*", str_replace('-', '', $uuid));
}

一个更紧凑的反解UUID函数,仅使用unpack()join()方法。 注意:你需要命名解包数组参数/键以避免被覆盖
function bin_to_uuid($bin){
  return join("-", unpack("H8time_low/H4time_mid/H4time_hi/H4clock_seq_hi/H12clock_seq_low", $bin));
}

对于较旧的MySQL版本,其中缺少uuid_to_bin()bin_to_uuid()函数:

DELIMITER $$
CREATE FUNCTION `fn_uuid_to_bin`(`s` CHAR(36)) RETURNS binary(16)
    DETERMINISTIC

RETURN UNHEX(REPLACE(s, '-', ''))$$

DELIMITER ;

DELIMITER $$
CREATE FUNCTION `fn_bin_to_uuid`(`b` BINARY(16)) RETURNS char(36) CHARSET utf8mb4
    DETERMINISTIC
BEGIN
  DECLARE hex CHAR(32);
  SET hex = HEX(b);
  RETURN LOWER(CONCAT(LEFT(hex, 8), '-', MID(hex, 9,4), '-', MID(hex, 13,4), '-', MID(hex, 17,4), '-', RIGHT(hex, 12)));
END$$

DELIMITER ;

6

如果使用php >= 5.4,则可以使用hex2binbin2hex函数:

$binary = hex2bin(str_replace('-', '', $value));


$string = bin2hex($value);
$string = preg_replace('/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/', '$1-$2-$3-$4-$5', $string);

或者使用函数来更好地组织代码:

function uuid2bin($uuid) {
   return hex2bin(str_replace('-', '', $uuid));
}

function bin2uuid($value) {
   $string = bin2hex($value);

   return preg_replace('/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/', '$1-$2-$3-$4-$5', $string);
}

对于 Laravel(使用 ID 字段):

public function setIdAttribute($value)
{
   $this->attributes[ 'id' ] = hex2bin(str_replace('-', '', $value));
}

public function getIdAttribute($value)
{
   $string = bin2hex($value);

   return preg_replace('/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/', '$1-$2-$3-$4-$5', $string);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接