Mysql if判断 类型隐形转换注意事项

本文分析了在MySQL查询中使用IF函数处理IP字符串时遇到的诡异问题,详细解释了IF函数如何进行隐式类型转换,并提供了一个正确的SQL查询示例来避免此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在做code review时,团队成员说sql中有个诡异的问题,某个登录IP对应的登录地点不不显示(该IP信息在IP地址表中已经维护),一起看下:

  • 表1: 登录日志表,sys_log_login,数据如下:
user_idlogin_iplogin_time
0010tW8gq3q60:0:0:0:0:0:0:12019-06-24 15:30:25
100191127.0.0.12019-06-25 10:20:35
  • 表2: IP地址表,data_ips,数据如下:
ipispcountryregioncity
0:0:0:0:0:0:0:1内网IPxxxxxx
127.0.0.1内网IPxxxxxx
  • sql:
SELECT a.login_ip, 
	IF(b.ip, CONCAT(b.isp, ' ', b.country, '-', b.region, '-', b.city ), '') login_address
FROM sys_log_login a LEFT JOIN data_ips b on a.login_ip = b.ip 
order by login_time desc;

登录IP在IP地址表中有维护则显示“运营商-国家-省-市”,否则显示空字符串,输出结果:
0:0:0:0:0:0:0:1 ‘’
127.0.0.1 ‘内网IP XX-XX-XX’

疑问:为啥登录ip 0:0:0:0:0:0:0:1,得到的是空字符串呢?
可能很多朋友都有这个疑问,仔细分析sql,这里有1个注意点:

  • mysql if 判断 隐性类型转换

我们不妨先看下mysql if判断语法:IF(expr1,expr2,expr3)
If expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns expr2; otherwise it returns expr3. IF() returns a numeric or string value, depending on the context in which it is used.

看上文sql,if (b.ip, exp2, ‘’),此处b.ip是字符串,即不是表达式也不是bool值,mysql处理的时候,会做2步:
1)会先将b.ip转换成float值;
2)根据得到的float值,非0则为true,0则为false;

0:0:0:0:0:0:0:1 转 float,得到0,所以if (b.ip, exp2, ‘’)取空字符串
127.0.0.1 转 float,得到127,所以if (b.ip, exp2, ‘’)取exp2,得到内网IP XX-XX-XX

正确sql如下:

SELECT a.login_ip, 
	IF(b.ip is not null, CONCAT(b.isp, ' ', b.country, '-', b.region, '-', b.city ), '') login_address
FROM sys_log_login a LEFT JOIN data_ips b on a.login_ip = b.ip 
order by login_time desc;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值