【发布时间】:2016-05-08 06:44:00
【问题描述】:
在没有 INET6_ATON / INET6_NTOA 的情况下将旧的 INET_ATON 值转换为新的二进制 INET6_ATON 值
我们在表中有现有数据,该字段的类型为 UNSIGNED INT,其中包含使用 INET_ATON() 创建的 IPv4 数据。
但现在我们在查询中移动到INET6_ATON(),并希望直接迁移数据而不为转换创建额外的数据库字段。
所以我将字段类型从UNSIGNED INT 更改为VARBINARY(16)。
新数据以二进制值形式存储为INET6_ATON()。
但是我们如何转换旧数据呢?
我已经尝试将现有值转换为整数并使用HEX 将它们转换为。使用INET6_ATON() 保存时,这给了我相同的十六进制字符串。
我是否遗漏了某些步骤或文字? 更新访问者 SET ip = HEX(CAST(ip AS UNSIGNED))
二进制数据不一样。在这种情况下,它被保存为十六进制值。使用BIN()、CONVERT() 和CAST() 没有帮助。
示例数据:
无符号整数字段中的旧 IP 值:
2130706433 ( = ip2long('127.0.0.1') )
varbinary 字段中显示的旧值:
32313330373036343333(= 2130706433)
varbinary 字段中显示的新值:
7f000001 (= INET6_ATON('127.0.0.1') )
我们不能直接使用INET6_ATON()/INET6_NTOA()进行转换。
我们是否应该使用 PHP 函数 inet_top() 和 inet_pton() 转换每一行的数据,或者是否有一个纯 SQL 解决方案而不需要一些 UDF,以便一次更新所有行?
似乎已经有一个类似的问题,但没有解决方案,并且 cmets 中提到的解决方案产生了错误的数据并且没有提供一些工作示例代码:Convert IPv6 to binary without INET6_ATON()
参考:
http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_inet6-aton
http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_inet6-ntoa
http://php.net/manual/en/function.inet-pton.php
http://php.net/manual/en/function.inet-ntop.php
【问题讨论】:
-
您似乎跳过了无法将 IPv4 地址直接转换为 IPv6 地址的问题。在您的示例中,
127.0.0.1是 IPv4 环回地址,但 IPv6 等效环回地址是::1。你正在尝试的东西没有任何意义。 -
这只是一个例子,但它的工作方式与预期一样。取 127.0.0.1 的 ip2long 的结果,获取它的十六进制并将其放入 inet_ntop 中,您再次得到 127.0.0.1。我们只需要将所有旧数据转换为新格式。旧数据只包含 IPv4 地址,所以这完全没问题。 inet_pton 和 inet_ntop 支持 IPv6 和 IPv4,INET6_NTOA 和 INET6_ATON 都支持。无需直接转换为 IPv6(由于 IPv6 地址可能不同,无法直接转换为 IPv6)。我不确定你的意思,但代码实际上是有道理的。它在文档中。
-
好的。只是不要尝试将结果用作 IPv6 地址,因为您将创建不受支持的 IPv6 地址。
-
不,我们不会这样做。在使用 INET6_NTOA 和 INET6_ATON 时,我们仍然可以使用 inet_pton / inet_ntop 获得正确的结果。新数据直接使用正确的格式,无需将它们从长(整数)格式转换为十六进制格式。它只是代表打包 IP 的实际格式;-)