我想了解为什么可以在数组内将null比较为相等,而不能将其比较为基元。
例如,以下查询演示:
SELECT NULL = NULL AS does_not_equal
, NULL::bool = NULL::bool AS does_equal
, NULL::int = NULL::int AS does_equal
, NULL::text = NULL::text AS does_equal
, ARRAY[NULL] = ARRAY[NULL] AS does_equal
, ARRAY[NULL]::bool[] = ARRAY[NULL]::bool[] AS does_equal
, ARRAY[NULL]::int[] = ARRAY[NULL]::int[] AS does_equal
, ARRAY[NULL]::text[] = ARRAY[NULL]::text[] AS does_equal
;
我理解为什么NULL=NULL对于基元来说是NULL,我也理解为什么比较复合类型会对其中两边都为NULL的字段进行真正的比较,主要是因为*=运算符会查看类型的二进制值。但是数组似乎不使用*=运算符,到目前为止,我在搜索中还找不到任何解释它的内容。
这是一个复杂的故事。
以下是SQL标准(ISO/IEC 9075-2)在“8.2<比较谓词>rdquo;:
设XV和YV是由<值表达式>sX和Y。结果:
X<comp op>Y
确定如下:
案例:
如果XV或
YV
X<comp op>Y
是未知的。
否则,
案例:
如果XV和YV的行类型,则设Xi,1(一)≤i≤N,表示<值表达式>其值和声明的类型是XV的i第个字段的值和声明类型,以及设Yi表示<值表达式>其值和声明的类型是YV的第i个字段的值和声明类型
的结果
X<comp op>Y
确定如下:
- X=Y为真当且仅当Xi=Yi对于所有i均为True
- X<Y是真当且仅当Xi=Yi对于所有i<n和Xn=Yn
- X=Y为假当且仅当NOT(Xi=Yi)对于某些i是真
- X<Y为假当且仅当X=Y为真或Y<X为真
- X<comp-op>Y是未知如果X<comp-op>Y既不是True也不是False
如果XV和YV1的数组类型和N2,则设Xi,1(一)≤i≤N1表示a<值表达式>其值和声明的类型为XV的第i个元素的Yi表示<值表达式>其值和声明的类型是YV的第i个元素的元素。的结果
X<comp op>Y
确定如下:
- X=Y如果N1=0(零)且N2=0(零),则True
- 如果N1=N2,则X=Y为真;对于所有i而言,Xi=Yi均为True
- X=Y为假当且仅当N1≠N2或NOT(Xi=Yi)为True,对于某些i
- X<comp-op>Y是未知如果X<comp-op>Y既不是True也不是False
这很令人困惑,例如,我没有看到任何规范可以将数组与等式运算符之外的其他运算符进行比较。
该标准偶尔也会自相矛盾。
*=
运算符仅适用于record
,不适用于数组。它的作用与=
基本相同,但效率更高,因为它不";排毒";值,如果它们的长度不同。
最好的办法是接受语义的现状。
PostgreSQL在这方面似乎没有遵循标准。
NULL本身是令人困惑的,NULL在复合或数组中更是如此
我找不到您描述的行为的文档。然而,对于记录和行构造函数,NULL
s被认为是相等的,这一点有明确的解释:
如果结果取决于比较两个NULL值或NULL和非NULL。在两个复合类型值为相比之下,两个NULL字段值被认为是相等的,而NULL是被认为大于非NULL。
数组不是复合类型。似乎也在使用类似的逻辑。