MySQL 返回一个空字段:CONCAT(非空1,空2,非空3)= NULL

13

我有一个使用 PHP 5 访问 MySQL 5 服务器上的 MyISAM 表的代码。查询看起来像这样:

SELECT CONCAT(fName1,' ',mName2,' ',lName3) AS userName 
    FROM users 
    WHERE level > 10
当没有填写mName时,我期望的输出是"fname lname",但实际上得到的是""(空字符串),返回的行数是正确的。我犯了哪些错误?
PHP代码:
<?php
$result = mysql_query($the_above_query);
while ($result_row = mysql_fetch_assoc($result)) {
    // do stuff with the name
    // except I'm getting empty strings in $result_row['userName']
}

表结构中的相关部分:

CREATE TABLE users {
    /* -snip- */ 
    `fName1` varchar(50) default NULL,      
    `mName2` varchar(50) default NULL,      
    `lName3` varchar(50) default NULL,      
    `level` int(11) default 0,      
    /* -snip- */ 
} ENGINE=MyISAM DEFAULT CHARSET=utf8;

此外,这种方式(在MySQL中进行列拼接)是否可行,或者应该将列提取到PHP中进行连接?


结果发现我得到了一个NULL;PHP将返回的NULL和空字符串("")看作相似,您需要使用===进行比较以查看区别。

6个回答

25

来自谷歌:http://bugs.mysql.com/bug.php?id=480

[2003年5月23日 4:32] Alexander Keremidarski

感谢您抽出时间给我们写信,但这不是一个错误。请仔细检查http://www.mysql.com/documentation/上提供的文档以及如何报告错误 的说明。

这是 CONCAT() 函数的预期行为。

从手册第6.3.2章节“字符串函数”中:

CONCAT(str1,str2,...) 返回连接参数后的字符串,如果任意一个参数为 NULL 则返回 NULL。

请改用 CONCAT_WS() 或使用 IFNULL() 函数包装可为空的参数。

CONCAT_WS 的文档和用法:http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat-ws


16

来自MYSQL文档

如果任何参数为NULL,则CONCAT()返回NULL。

你需要使用CONCAT_WS()

CONCAT_WS(separator,str1,str2,...)

但最好的方法是将其拉回并使用 PHP,因为如果您以后需要不同的格式或只想获取其中一个字段,您将必须进行另一个数据库调用。


+1 和非常感谢——我从未知道这个存在,但今晚我需要它! - Mark

11

在MySQL中,将任何字符串与NULL值连接会导致结果为NULL。你必须在使用IFNULL进行连接之前检查是否为NULL:

SELECT CONCAT(IFNULL(fName1,''),' ',IFNULL(mName2,''),' ',IFNULL(lName3,'')) AS userName 
FROM users 
WHERE level > 10

4

这是我想出的解决方案,包括Keeper和Ersatz的答案。然而系统不允许我给你们点赞 :(

CONCAT_WS(IFNULL(ts_usr_nameDetails.first_name,''),' ',IFNULL(ts_usr_lib_connectionNameDetails.first_name,'')) AS composerName

这样可以得到一些惊人的结果。


如果您正在使用 CONCAT_WS 并且分隔符(第一个参数)不为 NULL,则无需使用 IFNULL。 "CONCAT_WS() 不会跳过空字符串。但是,它会在分隔符参数后跳过任何 NULL 值。如果分隔符为 NULL,则结果为 NULL。" 请参见 http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat-ws。 - Dvir Berebi

1

你也可以使用COALESCE()函数来返回第一个非空值。像这样:

SELECT CONCAT(fName1,COALESCE(CONCAT(' ',mName2,' '),' '),lName3) AS userName 
  FROM users 
  WHERE level > 10

如果没有中间名,这也只会放置一个空格,并在中间名前后放置一个空格。
该函数的参考资料可以在此处找到: http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce

这是我认为最好的答案,因为您可以轻松地将 null 合并为一个空字符串:concat(address1,' ', coalesce(unit, '') ,' ', city,', ', state,' ', zip) 作为地址。 - Jage

1

这是基于@chocojosh的上面的解决方案和另一个问题MySQL/SQL:使用更新后的表本身的相关子查询进行更新的答案。

我遇到了类似的问题,但我试图连接一堆group_concats,其中一些是NULL,导致整行为NULL。目标是将其他表中的数据放入主表中的单个字段中,以允许全文搜索。

以下是有效的SQL。请注意,我为concat_ws制定的第一个参数是“ ”,这允许在全文字段的值之间添加空格。

希望这能帮助某人。

update
products target
INNER JOIN 
(
    select p.id, 
    CONCAT_WS(
    ' ',
        (select GROUP_CONCAT(field SEPARATOR ' ') from table1 where productId = p.id),
        p.title,' ', 
        (select GROUP_CONCAT(field, ' ', descriptions SEPARATOR ' ') from table2 where productId = p.id),
        (select GROUP_CONCAT(field SEPARATOR ' ') from table3 where productId = p.id),
        (select GROUP_CONCAT(field, ' ', catno SEPARATOR ' ') from table4 where productId = p.id),
        (select GROUP_CONCAT(field SEPARATOR ' ') from table5 where productId = p.id),
        (select GROUP_CONCAT(field SEPARATOR ' ') from table6 where productId = p.id),
        (select GROUP_CONCAT(field SEPARATOR ' ') from table7 where productId = p.id)
    ) as ft
    from products p
) as source
on target.id = source.id
set target.fulltextsearch = source.ft

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