可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have PHP 5 code accessing a MyISAM table on MySQL 5 server. The query looks like this:
SELECT CONCAT(fName1,' ',mName2,' ',lName3) AS userName
FROM users
WHERE level > 10
When there's no mName filled in, I am expecting output like "fname lname" , but I'm getting "" (empty string) instead (the number of rows returned is correct). Where am I making a mistake?
PHP code:
<?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']
}
Relevant part of table structure:
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;
(also, is this way (column concatenation in MySQL) a good idea, or should I fetch the columns to PHP and join them there?)
Turns out that I was getting back a NULL; PHP treats a returned NULL and empty string("") similarly, you'd have to compare with === to see the difference.
回答1:
From google: http://bugs.mysql.com/bug.php?id=480
[23 May 2003 4:32] Alexander Keremidarski
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.mysql.com/documentation/ and the instructions on
how to report a bug at http://bugs.mysql.com/how-to-report.php
This is doccumented behaviour of CONCAT() function.
From Manual chapter 6.3.2 String Functions
CONCAT(str1,str2,...)
Returns the string that results from concatenating the arguments. Returns NULL if any
argument is NULL
Use CONCAT_WS() instead or wrap NULLable paremeters with IFNULL() function.
Documentation and usage for CONCAT_WS: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat-ws
回答2:
From MYSQL docs
CONCAT() returns NULL if any argument
is NULL.
you want to use CONCAT_WS()
CONCAT_WS(separator,str1,str2,...)
But best bet is to just pull it back and use php cause if you need a different format or just one of those fields later you'll have to make another db call
回答3:
In MySQL concatenating any string to a NULL value results in NULL.
You have to check for NULL before concatenate using IFNULL:
SELECT CONCAT(IFNULL(fName1,''),' ',IFNULL(mName2,''),' ',IFNULL(lName3,'')) AS userName
FROM users
WHERE level > 10
回答4:
This was the solution I came up with which included Keeper and Ersatz answer. System would not allow me to vote you guys up though :(
CONCAT_WS(IFNULL(ts_usr_nameDetails.first_name,''),' ',IFNULL(ts_usr_lib_connectionNameDetails.first_name,'')) AS composerName
This allowed for some amazing results
回答5:
This is an answer based on the solution above by @chocojosh and another question here: MySQL/SQL: Update with correlated subquery from the updated table itself
I had a similar problem, but I was trying to concat a bunch of group_concats and some were NULL which caused the whole row to be NULL. The goal was to place data from other tables into a single field in the main table to allow fulltext searches.
Here is the SQL that worked. Note the first parameter for concat_ws I made ' ', this allowed for spaces between the values for the fulltext field.
Hope this helps someone.
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:
you could also the COALESCE()
function to return the first non-null value. Like so:
SELECT CONCAT(fName1,COALESCE(CONCAT(' ',mName2,' '),' '),lName3) AS userName
FROM users
WHERE level > 10
This would also only put one space if there was no middle name and a space before and after if there was a middle name.
Reference for this function can be found at: http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce