Postgresql

IS NOT DISTINCT FROM vs row-wise equal with =

  • September 11, 2018

查看以下查詢,

SELECT null IS NOT DISTINCT FROM null AS indf,
 null = null AS eq;
indf | eq 
------+----
t    | 

從這裡我們可以看到IS NOT DISTINCT FROMis的結果,以及istrue的結果。然後從邏輯上遵循以下內容,eq``false

-- 1 rows
SELECT *
FROM ( VALUES (null) ) AS t(a)
JOIN ( VALUES (null) ) AS g(a)
 ON t.a IS NOT DISTINCT FROM g.a;

-- 0 rows
SELECT *
FROM ( VALUES (null) ) AS t(a)
JOIN ( VALUES (null) ) AS g(a)
 ON t.a = g.a;

因為如果條件返回null失敗join。但是,這讓我失望,逐行比較

-- returns 1 row.
SELECT *
FROM ( VALUES (null) ) AS t(a)
JOIN ( VALUES (null) ) AS g(a)
 ON (t) IS NOT DISTINCT FROM (g);

-- also returns one row.
SELECT * FROM ( VALUES (null) ) AS t(a)
JOIN ( VALUES (null) ) AS g(a)
 ON (t) = (g);

為什麼按行比較對待nulls 與標量比較不同?是否有IS NOT DISTINCT FROM逐行比較的意義?

此行為記錄在復合類型比較下,

NULL如果結果取決於比較兩個值或 aNULL和非,則 SQL 規範要求逐行比較返回 NULL NULLPostgreSQL 僅在比較兩個行建構子的結果(如 9.23.5 節)或將行建構子與子查詢的輸出進行比較(如 9.22 節)時才會這樣做。在比較兩個複合類型值的其他上下文中,兩個NULL欄位值被認為是相等的,並且 aNULL被認為大於非NULL. 為了使復合類型具有一致的排序和索引行為,這是必要的。

這實質上意味著標準行為只能在以下語法中看到(ROW()是行建構子):

SELECT * FROM ( VALUES (null) ) AS t(a)
JOIN ( VALUES (null) ) AS g(a)
 ON ROW(t.*) = ROW(g.*);

相對,

SELECT * FROM ( VALUES (null) ) AS t(a)
JOIN ( VALUES (null) ) AS g(a)
 ON ROW(t.*) IS NOT DISTINCT FROM ROW(g.*);

僅使用帶有類型的 ROW 建構子也不起作用ON ROW(t) = ROW(g)

引用自:https://dba.stackexchange.com/questions/217324