如果任何字段包含NULL,MySQL CONCAT函数将返回NULL。

245

我在我的名为“devices”的表中有以下数据

affiliate_name  affiliate_location  model     ip             os_type    os_version 

cs1             inter               Dell     10.125.103.25   Linux      Fedora  
cs2             inter               Dell     10.125.103.26   Linux      Fedora  
cs3             inter               Dell     10.125.103.27   NULL       NULL    
cs4             inter               Dell     10.125.103.28   NULL       NULL    

我执行了以下查询

SELECT CONCAT(`affiliate_name`,'-',`model`,'-',`ip`,'-',`os_type`,'-',`os_version`) AS device_name
FROM devices

它返回以下结果

cs1-Dell-10.125.103.25-Linux-Fedora
cs2-Dell-10.125.103.26-Linux-Fedora
(NULL)
(NULL)

如何摆脱这种情况,使其忽略NULL,并得到结果

cs1-Dell-10.125.103.25-Linux-Fedora
cs2-Dell-10.125.103.26-Linux-Fedora
cs3-Dell-10.125.103.27-
cs4-Dell-10.125.103.28-

2
刚刚也遇到了这个问题。我认为默认行为近乎疯狂。这与最小惊讶编程的精神恰恰相反。 - Joshua Pinter
7个回答

400

通过将其包装在COALESCE中,将NULL值转换为空字符串。

SELECT CONCAT(COALESCE(`affiliate_name`,''),'-',COALESCE(`model`,''),'-',COALESCE(`ip`,''),'-',COALESCE(`os_type`,''),'-',COALESCE(`os_version`,'')) AS device_name
FROM devices

1
你可以使用 if 选择 CONCAT(if(affiliate_name is null ,'',affiliate_name),'- ',if(model is null ,'',affiliate_name)) 作为设备的型号。 - Dinesh Rabara
11
对于那些像我一样想知道COALESCE函数是什么的人:它返回传递给它的第一个非NULL值参数(如果所有参数都为NULL,则返回NULL)。通过将空字符串作为第二个参数传递,您可以确保它不会返回NULL - Jo.
8
MySQL有一个IFNULL(arg, default)函数,它的语法与COALESCE相同。 - Vasilii Suricov
无法正常工作,当连接列A =“data person”与列B = null值时,仍返回null值。有人知道为什么吗? - Yogi Arif Widodo
啊,我们不能使用COALESCE(column,null),我复制了你的代码,现在它可以工作了。但是对于MySQL 8,我们只需使用COALESCE(column, ''),如果我们使用''括号,它会返回未知列,如果我们在定义列后使用null,则如果某个值为null,则返回null。 - Yogi Arif Widodo
显示剩余2条评论

166

请使用CONCAT_WS代替:

CONCAT_WS()不会跳过空字符串,但在分隔符参数后面跳过任何NULL值。

SELECT CONCAT_WS('-',`affiliate_name`,`model`,`ip`,`os_type`,`os_version`) AS device_name FROM devices

对不起,Neeraj,我在Concat和WS之间漏掉了下划线,请使用CONCAT_WS()再试一次。我已经更新了答案,请检查。 - Gurmeet
12
请注意,此解决方案会隐藏整个“列”(包括分隔符),如果中间字段为NULL。因此,此答案仅在只有最后一个字段可能为NULL的情况下才正确。根据您的需要,下面的COALESCE()解决方案可能更好。 - Jannes
1
只有在您希望每个成员都由相同的分隔符分隔时,此方法才有效。CONCAT没有这种限制。我在这里发布了答案解决方案。 - patrick
1
危险:SELECT CONCAT_WS(';',1,NULL)SELECT CONCAT_WS(';',NULL,1) 相同。两者都会返回 1。如果你想要的是 1;;1,那么这就是一个问题。 - giordano

19

CONCAT_WS在第一个字段为Null时仍会产生null。我通过在开头添加一个零长度字符串来解决这个问题,如下所示:

CONCAT_WS('', field1, field2, ...)

CONCAT_WS("",`affiliate_name`,'-',`model`,'-',`ip`,'-',`os_type`,'-',`os_version`)

然而

CONCAT("",`affiliate_name`,'-',`model`,'-',`ip`,'-',`os_type`,'-',`os_version`) 

当第一个字段为Null时,会产生空值(Null)。


显然,因为第一个字段是它将与之连接的字符串(WS=with string)。 - Bouke Versteegh
5
CONCAT_WS 是 Concatenate With Separator 的缩写。第一个参数是分隔符,不能为空。这可能是你想要的替代方式:CONCAT_WS("-", affiliate_name, model, ip, os_type, os_version) - encrest

15

如果您希望在 CONCAT_WS 中像 CONCAT 一样具有相同的灵活性(例如,如果您不想在每个成员之间使用相同的分隔符),请使用以下方法:

SELECT CONCAT_WS("",affiliate_name,':',model,'-',ip,... etc)

12

12
SELECT CONCAT(isnull(`affiliate_name`,''),'-',isnull(`model`,''),'-',isnull(`ip`,''),'-',isnull(`os_type`,''),'-',isnull(`os_version`,'')) AS device_name
FROM devices

20
MySQL中使用IFNULL()代替ISNULL()。 - Jeffrey Nicholson Carré

3

你可以像下面这样使用if语句:

select CONCAT(if(affiliate_name is null ,'',affiliate_name),'- ',if(model is null ,'',affiliate_name)) as model from devices

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