MySQL возвращает пустое поле: CONCAT (nonEmpty1, empty2, nonEmpty3) = NULL

У меня есть код PHP 5, доступ к таблице MyISAM на сервере MySQL 5. Запрос выглядит следующим образом:

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 и пустую строку ("") аналогично, вам нужно будет сравнить с ===, чтобы увидеть разницу.

Ответы

Ответ 1

Из google: http://bugs.mysql.com/bug.php?id=480

[23 мая 2003 4:32] Александр Керемидарский

Спасибо, что нашли время написать нам, но это не Жук. Пожалуйста, дважды проверьте документацию на http://www.mysql.com/documentation/ и инструкции по как сообщить об ошибке в http://bugs.mysql.com/how-to-report.php

Это документированное поведение функции CONCAT().

В главе "Руководство" 6.3.2 "Строковые функции"

CONCAT (str1, str2,...) Возвращает строку, которая возникает при объединении аргументов. Возвращает NULL, если таковой имеется аргумент NULL

Вместо этого используйте CONCAT_WS() или оберните пареметры NULLable функцией IFNULL().

Документация и использование для CONCAT_WS: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat-ws

Ответ 2

Из документов MYSQL

CONCAT() возвращает NULL, если любой аргумент имеет значение NULL.

вы хотите использовать CONCAT_WS()

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

Но лучше всего просто вернуть его и использовать php-причину, если вам нужен другой формат или только одно из этих полей позже, вам придется сделать другой вызов db

Ответ 3

В MySQL, связывающем любую строку с значением NULL, получается NULL. Вы должны проверить NULL перед конкатенацией, используя IFNULL:

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

Это позволило сделать некоторые удивительные результаты

Ответ 5

Это ответ на основе вышеизложенного решения @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

Ответ 6

вы также можете использовать функцию 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