跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

SQL如何进行IP地址与数字转换_INET_ATON与INET_NTOA函数

INET_ATON仅支持IPv4,IPv6需用INET6_ATON;传入非法格式或IPv6静默返回0,非报错;存IPv4须用INT UNSIGNED,IPv6须用VARBINARY(16);混合场景推荐统一用INET6_*函数。 MySQL里用
INET_ATON
转IP字符串为整数,但IPv6不支持 直接说结论:
INET_ATON
只处理IPv4,输入
"192.168.1.1"
返回整数
3232235777
;传入IPv6(如
"::1"
)或非法格式(如
"256.1.1.1"
)会静默返回
0
,不是报错——这是最容易踩的坑。 常见错误现象:WHERE条件里写
WHERE ip_int = INET_ATON('192.168.1.1')
,结果查不到数据,其实是因为字段里存的是IPv6,或者原始IP有空格/换行没trim。 必须提前清洗输入:
TRIM(BOTH FROM ' 192.168.1.1 ')
IPv4地址段超界(如
"256.0.0.0"
)也返回
0
,建议加校验:
INSTR('192.168.1.1', ':') = 0
先排除IPv6
INET_ATON
返回的是无符号32位整数,存进数据库时字段类型得是
INT UNSIGNED
,否则高位溢出变负数 用
INET_NTOA
把整数转回IPv4字符串,别在SELECT里盲目套用
INET_NTOA
是
INET_ATON
的逆操作,但只认32位无符号整数值。传入负数、NULL或超出范围的数(比如
4294967296
),结果是
NULL
,不会报错也不会提示。 典型误用场景:日志表里IP存的是
BIGINT
,为了兼容IPv6后来改用
INET6_ATON
,但旧SQL还留着
INET_NTOA(ip_int)
,一执行就大片
NULL
。 确认源字段确实是IPv4转换来的整数,且类型为
INT UNSIGNED
如果字段可能混IPv6,先判断:
CASE WHEN ip_int > 0 THEN INET_NTOA(ip_int) ELSE NULL END
不要在ORDER BY里用
INET_NTOA
做排序——函数计算开销大,且无法走索引 IPv6必须换
INET6_ATON
和
INET6_NTOA
,它们返回的是二进制值
INET6_ATON
返回
VARBINARY(16)
,不是整数。这意味着你不能用
=
直接比大小,也不能塞进INT字段里存——这是和IPv4函数最根本的区别。 常见错误:把
INET6_ATON('::1')
结果插入
CHAR(39)
字段,看起来像
"00000000000000000000000000000001"
,其实是乱码,因为二进制被当字符串转义了。 存IPv6必须用
VARBINARY(16)
字段类型 比较用
=
即可:
WHERE ip_bin = INET6_ATON('2001:db8::1')
想看可读形式,SELECT里用
INET6_NTOA(ip_bin)
,但别在WHERE里用它做条件——没法走索引 注意:MySQL 5.6.3+才支持,低版本只能靠字符串存储或第三方函数 混合IPv4/IPv6场景下,统一用
INET6_*
函数更稳妥 哪怕当前全是IPv4,只要未来可能接入IPv6,就别碰
INET_ATON
/
INET_NTOA
。因为
INET6_ATON
对IPv4也兼容,会自动补前导零转成16字节二进制,而
INET_ATON
对IPv6完全无能为力。 性能影响很小,但类型安全高得多。唯一代价是存储空间从4字节涨到16字节,对绝大多数业务不是瓶颈。 存IPv4时:
INET6_ATON('192.168.1.1')
→
00000000000000000000FFFFC0A80101
(16字节) 查IPv4仍可用
INET6_NTOA
还原,输出还是
"192.168.1.1"
应用层无需区分协议,数据库字段类型和SQL写法完全一致 真正麻烦的是历史数据迁移:老表用
INT
存IPv4,新逻辑用
VARBINARY(16)
,中间没有自动转换桥接。这点得在改表前就想清楚,别等上线才发现WHERE里混用两个函数导致结果错乱。

相关文章