为什么在Postgres中,null || null返回null值,但concat(null, null)返回空字符串?

5

我正在尝试理解在Postgres中使用空值时concat()和||之间的区别。为什么如果拼接的两个部分都是null,concat()会返回一个空字符串?

以这个查询为例:

SELECT concat(NULL,NULL) AS null_concat, NULL||NULL AS null_pipes, 
concat(NULL,NULL) IS NULL is_concat_null, NULL||NULL IS NULL is_pipe_null

will return:

enter image description here

我知道concat()会忽略null,但如果concat中所有的值都是null,那么预期的结果不应该是null吗?这是postgres中所有函数的典型行为吗?我在文档中没有找到有关此情况的任何信息。
编辑:
我想到可能这是任何字符串函数的预期结果,但事实并非如此。如果传递null值,则upper()和left()都返回null:
SELECT concat(NULL), NULL||NULL, UPPER(null), left(NULL,1)

结果:

enter image description here


2
CONCAT 的想法并不是因为其中一个连接部分为空而使字符串为空。因此,空值不会使结果为空;你仍然得到一个字符串。这就是论点所在 :-) 尽管如此,我同意这有点出乎意料,应该在文档中明确提到。 - Thorsten Kettner
1
似乎concat的行为类似于聚合函数(例如SUM忽略NULL)。此外,请注意在文档中,只有concatconcat_ws这两个函数声明:“忽略NULL参数”。因此,我认为默认行为是将NULL视为优先级最高(这反映了SQL标准)。 - Zack
1个回答

1
在concat()函数中:
text concat(str "any",...)  Concatenate all arguments. NULL arguments are ignored.

注意:NULL参数将被忽略。

想象一下:

concat()的输入参数是动态的。

因此,当我们写:concat('a',null,null,null,null) => 我们实际上写了:concat('a')

(与运算符||不同,它会毁掉所有的NULL值)


in || 运算符:

字符串连接运算符(||)仍然接受非字符串输入,只要至少有一个输入是字符串类型即可。

因此,NULL||NULL 的语法是错误的。

但为什么不报错呢? 因为在连接操作中,如果我们不拒绝 NULL(像连接函数一样),它们将会淹没一切。

SELECT NULL ||'aaa'||'bbb'||'ccc'||'ddd'

输出:

NULL

更多信息

注意:在PostgreSQL 8.3之前,由于存在从这些数据类型到文本的隐式强制转换,这些函数会悄无声息地接受多个非字符串数据类型的值。然而,由于它们经常导致令人惊讶的行为,因此已经删除了这些强制转换。但是,字符串连接运算符(||)仍然接受非字符串输入,只要至少一个输入是字符串类型即可,如表9-6所示。对于其他情况,如果需要复制以前的行为,请插入显式强制转换为文本。

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