【问题标题】:MySQL: match duplicate IPv6 subnet prefixMySQL:匹配重复的 IPv6 子网前缀
【发布时间】:2021-09-10 09:59:20
【问题描述】:

我无法找到正确返回(和匹配)存储在 DB 中的 IPv6 地址的前 /64 位的正确方法,例如:2a02:a420:0003:7dbc:0002:0001:b693:9622

我需要检索表中使用相同 IPv6 网络/子网(/64 位)的条目

注意:该表包括 IPv4 和 IPv6 地址

我正在使用 MySQL Workbench 8.0

【问题讨论】:

  • 您使用什么数据类型来存储您的 ipv6 地址?
  • 使用的数据类型是 VARCHAR(50)

标签: mysql analytics ipv6 subnet


【解决方案1】:

假设您将 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 的索引/过滤内容吗?如果他们这样做,那就太好了。

【讨论】:

  • 非常感谢!在你的帮助下,我离我需要实现的目标更近了,我发现我的问题不够清楚,我的错误;)使用数据库的查看器只能处理 2a02:a420:0003:7dbc 作为输入,而不是缩短的 IPv6地址从 YMD >= '2021-01-01 的订单中选择 SUBSTRING(HEX(INET6_ATON(IPADRES)),1,16) 作为 subtring_ipv6, count(SUBSTRING(HEX(INET6_ATON(IPADRES)),1,16)) 作为 count_subtring_ipv6 ' and is_ipv6(IPADRES) = 1 group by SUBSTRING(HEX(INET6_ATON(IPADRES)),1,16);上面的语法返回缩短的版本,有没有办法让它返回不缩短?
猜你喜欢
  • 1970-01-01
  • 2015-02-11
  • 2019-01-11
  • 2012-12-31
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多