假设您将 addrcolumn 存储为带有 IPv6 地址的 VARCHAR(39) 文本字符串,并且您将 @matchaddr 作为文本字符串包含 您要匹配的 /64 范围内的有效地址。
你可以像这样得到addrcolumn的前16个十六进制数字:
SUBSTRING(HEX(INET6_ATON(addrcolumn)),1,16)
所以你可以像这样使用 LIKE 运算符进行匹配。
WHERE HEX(INET6_ATON(addrcolumn))
LIKE CONCAT(SUBSTRING(HEX(INET6_ATON(@matchaddr)),1,16), '%')
在字符串操作函数之后,它看起来像
WHERE `2a02a42000037dbc00020001b693962a' LIKE '2a02a42000037dbc%'
您需要与 INET6_ATON() 混用,因为 IPv6 地址通常用两个冒号缩短,这意味着一堆像这样的零:
2a02:a420::2:1:b693:9622
INET6_ATON() 正确处理了这个问题。
编辑但是,如果您假设您的 ipv6 地址表示永远永远包含任何通过 : 或 :1:2: 样式缩写的缩写,您可以这样做与 LIKE 匹配的子字符串。
WHERE addrcolumn LIKE CONCAT(SUBSTRING(@matchaddr)),1,19), '%')
注意 19 个字符的子字符串。这看起来像
WHERE `2a02:a420:0003:7dbc:0002:0001:b693:962a'
LIKE '2a02:a420:0003:7dbc%'
注意:真实用户会违反您的假设。
在 MySQL 8+ 中,您可以将二进制表示转换为未缩写的文本表示,如下所示:
SELECT LOWER(
SUBSTRING(
REGEXP_REPLACE(HEX(binaryAddr), '([0-9a-f]{4})', '$1:'), 1, 39))
在 MariaDB 10+ 中是:
SELECT LOWER(
SUBSTRING(
REGEXP_REPLACE(HEX(binaryAddr), '([0-9a-f]{4})', '\\1:'), 1, 39))
MariaDB 或 MySQL 团队有一天会添加一些特定于 IPv6 的索引/过滤内容吗?如果他们这样做,那就太好了。