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