我写了一个类似这样的T-SQL语句(最初的看起来不同,但我想在这里给出一个简单的例子):

SELECT first_name + 
    CASE last_name WHEN null THEN 'Max' ELSE 'Peter' END AS Name
FROM dbo.person

此语句没有任何语法错误,但case-clause总是选择else部分-如果last_name为空也是如此。但是为什么呢?

我想做的是联合first_name和last_name,但如果last_name为空,整个名称变成空:

SELECT first_name +
   CASE last_name WHEN null THEN '' ELSE ' ' + last_name END AS Name 
FROM dbo.person

你知道问题出在哪里吗?


当前回答

在SQL Server 2017中,微软引入了一个带有分隔符的连接函数,仅针对您的情况:

SELECT CONCAT_WS(' ', first_name, last_name) FROM dbo.person

CONCAT_WS跳过NULL值,但不跳过空字符串。

有趣的是,MySQL早在十多年前就引入了CONCAT_WS。

其他回答

问题是null不被认为等于它自己,因此子句永远不匹配。

你需要显式检查null:

SELECT CASE WHEN last_name is NULL THEN first_name ELSE first_name + ' ' + last_name

try:

SELECT first_name + ISNULL(' '+last_name, '') AS Name FROM dbo.person

这将把空格加到姓氏上,如果它为空,整个空格+姓氏将变为null,您只得到一个名字,否则您将得到一个firts+空格+姓氏。

只要设置了空字符串连接的默认设置,这就可以工作:

SET CONCAT_NULL_YIELDS_NULL ON 

这应该不是一个问题,因为在未来的SQl Server版本中,OFF模式将会消失

给定你的查询,你也可以这样做:

SELECT first_name + ' ' + ISNULL(last_name, '') AS Name FROM dbo.person

NULL不等于任何东西。case语句基本上是说当value = NULL ..它永远不会击中。 还有一些系统存储过程用您的语法写得不正确。参见sp_addpullsubscription_agent和sp_who2。 希望我知道如何通知微软的这些错误,因为我不能改变系统存储过程。

Jason发现了一个错误,所以这可以工作…

有人能确认其他平台的版本吗? SQL服务器:

SELECT
CASE LEN(ISNULL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

MySQL:

SELECT
CASE LENGTH(IFNULL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

Oracle:

SELECT
CASE LENGTH(NVL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName