SQL: 二进制转IP地址

12

我正在尝试将一个二进制IP转换为易读的IP

SELECT HEX( `ip_bin` ) FROM `log_metadata`

给了我 4333D26E000000000000000000000000

还有

SELECT INET_NTOA(0x4333D26E)

给了我 67.51.210.110

所以我尝试了:

SELECT
  SUBSTRING( CONVERT(HEX(`ip_bin`), CHAR(32)), 1, 8 ) AS `A`
, INET_NTOA( 
  SUBSTRING( CONVERT(HEX(`ip_bin`), CHAR(32)), 1, 8 ) 
                                                     ) AS `B`
, INET_NTOA(hex(`ip_bin`))  AS `C`
, INET_NTOA(`ip_bin`)       AS `D`
FROM `log_metadata`

但是我只得到

+----------+------------+------------+---------+
| A        | B          | C          | D       |
+----------+------------+------------+---------+
| 4333D26E | 0.0.16.237 | 0.0.16.237 | 0.0.0.0 |
+----------+------------+------------+---------+

有什么建议吗?


可能是字符串“A”前缺少了“0x”。 - Niloct
尝试过了。它只返回了 00.0.0.0 - redolent
4个回答

12

当使用Mysql 5.6.3或更高版本时,最好直接使用INET6_NTOA - 它接受二进制字符串并返回其人类可读格式。它还支持IPv4和IPv6地址,并相应地返回格式。因此,在您的示例中,您将使用:

SELECT INET6_NTOA( `ip_bin` ) FROM `log_metadata`

并且应该获得易于理解的结果。


1
  • 适当的存储类型是VARBINARY(16)- VAR,因为它对于ipv4是4位,对于ipv6是16位。
- hanshenrik

8
mysql> select inet_ntoa(conv('4333d26e', 16, 10));
+-------------------------------------+
| inet_ntoa(conv('4333d26e', 16, 10)) |
+-------------------------------------+
| 67.51.210.110                       |
+-------------------------------------+
1 row in set (0.00 sec)

请检查它是否也可以正常工作 =)

编辑

问题在于 inet_ntoa 似乎解析的是十进制 字符串 的数字表示,而不是十六进制的,或者是从十六进制整数中解析。比较一下:

mysql> select inet_ntoa(0x4333d26e);
+-----------------------+
| inet_ntoa(0x4333d26e) |
+-----------------------+
| 67.51.210.110         |
+-----------------------+
1 row in set (0.02 sec)

mysql> select inet_ntoa('0x4333d26e');
+-------------------------+
| inet_ntoa('0x4333d26e') |
+-------------------------+
| 0.0.0.0                 |
+-------------------------+
1 row in set, 1 warning (0.00 sec)

编辑

这个方法更简单,看起来也有效:

SELECT INET_NTOA(CONV(ip_bin, 2, 10)) FROM log_metadata

1
我最终使用了 INET_NTOA( CONV( SUBSTRING(HEX( ip_bin ), 1, 8), 16, 10 )) - redolent
尝试这个:SELECT INET_NTOA(CONV(ip_bin, 2, 10)) FROM log_metadata - Niloct
没起作用。问题在于某些原因导致位数在左边 - 0x4333D26E000000000000000000000000 - redolent
你可以尝试将它们向右移动。Mysql有移位运算符。 - Niloct
MySQL似乎对那些很不喜欢。我最好的猜测是它将该值解析为“整数最大值”。 - redolent
显示剩余2条评论

7

我发现我需要先调用 HEX 函数将我的二进制字段转换为十六进制字符串,所以以下代码对我有效:

select inet_ntoa(conv(HEX(ip_bin), 16, 10)) from log_metadata

3

请注意~这适用于较新版本的MySQL

 SELECT INET6_NTOA( `ip_bin` ) FROM `log_metadata`

这与

相同。
SELECT INET_NTOA( CONV( SUBSTRING(HEX(`ip_bin` ), 1, 8), 16, 10 )) FROM log_metadata;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接