【问题标题】:MySQL CONCAT returns NULL if any field contain NULL如果任何字段包含 NULL,MySQL CONCAT 将返回 NULL
【发布时间】:2013-03-22 09:38:29
【问题描述】:

我的表“设备”中有以下数据

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-

【问题讨论】:

  • 刚刚也遇到了这个问题。我会认为这是默认操作几乎是疯了。与意外最少的编程正好相反。

标签: mysql sql null concat


【解决方案1】:

原因:

MySQL :: Reference Manual :: 12.8 String Functions and Operators 说:

如果任何参数为 NULL

CONCAT() 返回 NULL

解决方案:

MySQL :: Reference Manual :: 12.5 Flow Control Functions 说:

IFNULL(expr1,expr2) 

如果expr1不是NULLIFNULL()返回expr1;否则返回 expr2。

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

【讨论】:

    【解决方案2】:

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

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

    然而

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

    当第一个字段为 Null 时产生 Null。

    【讨论】:

    • 很明显,因为第一个字段是要连接的字符串(WS = with string)
    • CONCAT_WS 是 Concatenate With Separator 的缩写。第一个参数是分隔符,不能为空。这可能是您想要的:CONCAT_WS("-", affiliate_name, model, ip, os_type, os_version)
    【解决方案3】:

    改用CONCAT_WS

    CONCAT_WS() 不会跳过空字符串。但是,它会跳过分隔符参数之后的任何 NULL 值。

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

    【讨论】:

    • 抱歉,我错过了 Concat 和 WS 之间的 '_' 请使用 CONCAT_WS() 重试。我已更新答案,请检查,
    • 请注意,如果中间字段之一为 NULL,此解决方案将隐藏完整的“列”(包括分隔符)。所以这个答案只有在只有最后一个字段可以为 NULL 的情况下才是正确的。根据您的需要,下面的 COALEASE() 答案可能会更好。
    • 这仅在您希望每个成员由相同的分隔符分隔时才有效。 CONCAT 没有这个限制。我在这里发布了解决方案作为答案
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

      要在 CONCAT_WS 中获得与 CONCAT 中相同的灵活性(例如,如果您不希望每个成员之间使用相同的分隔符),请使用以下命令:

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

      【讨论】:

        【解决方案6】:
        SELECT CONCAT(isnull(`affiliate_name`,''),'-',isnull(`model`,''),'-',isnull(`ip`,''),'-',isnull(`os_type`,''),'-',isnull(`os_version`,'')) AS device_name
        FROM devices
        

        【讨论】:

        • 在 mysql IFNULL() 中而不是 ISNULL()
        【解决方案7】:

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

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

        【讨论】:

        • 您可以使用 if select CONCAT(if(affiliate_name is null ,'',affiliate_name),'- ',if(model is null ,'',affiliate_name)) 作为设备模型
        • 对于那些想知道COALESCE 函数做了什么的人:它返回第一个传递给它的非NULL 值参数(或者NULL,如果所有参数都是NULL )。通过传递一个空字符串作为第二个参数,您保证它不会返回NULL
        • mysql 有 IFNULL(arg, default) 而不是 COALESCE,语法相同
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-07
        相关资源
        最近更新 更多