为什么这个字符串到二进制的转换不起作用?

Why isn't this string to binary conversion working?

我将 IPv6 地址存储为 BINARY(16) 并尝试使用十六进制表示来搜索它们,例如:FFFFFFFF000000000000000000000000.

这个有效:

SELECT * FROM ipv6 WHERE HEX(address) = 'FFFFFFFF000000000000000000000000'

然而,这不是:

SELECT * FROM ipv6 WHERE address = CONV('FFFFFFFF000000000000000000000000', 16, 2)

没有错误消息,只是 return 没有任何结果。 MySQL 是否无法使用 CONV() 处理转换?

我可以使用第一个选项,但我想第二个选项在大型数据库中要快得多,因为它不必转换 table.

中的每个地址

更新:

正如杰克指出的那样,

UNHEX() 似乎效果很好。使用 CONV() 的标准转换(从 5.6 开始)似乎最大为 8 字节(64 位)或十六进制形式 FFFFFFFFFFFFFFFF,因此它无法处理完整的 128 位 ipv6 地址。

经过深思熟虑,我相信 Salman 的回答是处理十六进制的最佳方式(使用十六进制文字)。但是,如果您在 PHP 中使用参数绑定,那么 unhex(),afaik 是必需的,因为将添加引号并将阻止 MySQL 将其评估为文字与 char 字符串。

因此您必须选择最适合您的解决方案。十六进制文字要快一点,但如果您要处理用户输入,那么使用参数绑定的 unhex 可能是最好的解决方案。

如果不想把每一项都转成十六进制,可以反其道而行之:

SELECT *
FROM ipv6
WHERE address = UNHEX('FFFFFFFF000000000000000000000000');

这将按照您的预期进行二进制字符串比较。

您可以使用 hexadecimal literals:

SELECT * FROM ipv6 WHERE address = 0xFFFFFFFF000000000000000000000000;
SELECT * FROM ipv6 WHERE address = X'FFFFFFFF000000000000000000000000';

如果你正在使用 PDO,你可以简单地这样做:

# insert packed address
$stmt = $db->prepare("INSERT INTO ipv6(address) VALUES (?)");
$stmt->execute(array(inet_pton("2001:0DB8:85A3:0000:0000:8A2E:0370:7334")));

# select packed address    
$stmt = $db->prepare("SELECT * FROM ipv6 WHERE address = ?");
$stmt->execute(array(inet_pton("2001:0DB8:85A3:0000:0000:8A2E:0370:7334")));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

# verify the result
echo inet_ntop($rows[0]["address"]);
# 2001:db8:85a3::8a2e:370:7334