为什么这个字符串到二进制的转换不起作用?
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
我将 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