具有另一个复杂类型字段的复杂类型中的空检测

Null detection in a complex type with field of another complex type

我有一个复杂类型,其中包含另一个复杂类型的单个字段:

-- Result: IS NULL = FALSE, IS NOT NULL = TRUE
-- Looks OK
CREATE TYPE bar_ok AS (id int);
CREATE TYPE foo_ok AS (val bar_ok);

CREATE OR REPLACE FUNCTION nulltest_ok()
returns foo_ok as
$$
DECLARE
 _r foo_ok;
 _a bool;
 _b bool;
BEGIN
 _a := _r IS NULL;
 _b := _r IS NOT NULL;
 RAISE NOTICE 'is null %', _a;
 RAISE NOTICE 'is not null %', _b;

 RETURN _r;
END;
$$ LANGUAGE plpgsql;

SELECT * FROM nulltest_ok();

-- RESULT:
-- NOTICE:  is null f
-- NOTICE:  is not null t

具有复杂和非复杂类型字段的复杂类型:

-- Result: IS NULL = FALSE, IS NOT NULL = FALSE
-- Is that OK?
CREATE TYPE bar_bad AS (id int);
CREATE TYPE foo_bad AS (id int, val bar_bad);

CREATE OR REPLACE FUNCTION nulltest_bad()
returns foo_bad as
$$
DECLARE
 _r foo_bad;
 _a bool;
 _b bool;
BEGIN
 _a := _r IS NULL;
 _b := _r IS NOT NULL;
 RAISE NOTICE 'is null %', _a;
 RAISE NOTICE 'is not null %', _b;

 RETURN _r;
END;
$$ LANGUAGE plpgsql;

SELECT * FROM nulltest_bad();

-- RESULT:
-- NOTICE:  is null f
-- NOTICE:  is not null f
  1. 是否可以使用嵌套复杂类型测试复杂类型的空值?

  2. 是否可以在没有 "empty" 嵌套复杂类型的情况下获得序列化复杂类型?

    -- Type
    CREATE TYPE some_type AS (
     id int,
     some_complex_type_here bar,
     name varchar
    )
    -- Now - serialized complex type with nested complex type (null):
    (1,(),)
    -- Goal:
    (1,,)
    

我是运行 PostgreSQL 9.4.0, Visual C++ build 1800, 64-bit (Windows 7).

Q1

  1. Is it possible to test null value of complex type with nested complex types?

您不是第一个对此感到困惑的人。对于简单类型,IS NULLIS NOT NULL 是逆运算。要么是真的,要么是另一个。但对于行值或复合(复杂)类型而言并非如此。 IS NOT NULL 只有 returns TRUE 如果(且仅当)每一列都是 NOT NULLPer documentation:

Note: If the expression is row-valued, then IS NULL is true when the row expression itself is null or when all the row's fields are null, while IS NOT NULL is true when the row expression itself is non-null and all the row's fields are non-null. Because of this behavior, IS NULL and IS NOT NULL do not always return inverse results for row-valued expressions, i.e., a row-valued expression that contains both NULL and non-null values will return false for both tests. This definition conforms to the SQL standard [...]

大胆强调我的。

但是复杂类型初始化为NULL!

嗯,不完全。复合类型用所有嵌套的元素 NULL初始化,递归地嵌套复合类型也是如此。并且复合类型 containing 复合类型包含 anything 作为一个整体不被认为是 NULL。比较混乱...

有一种方法可以解决这个问题:row-wise comparison is slightly different from composite type comparison. You can construct a row from the decomposed type and test with IS NULL. This does what you are looking for. There is an example in the manual:

SELECT ROW(table.*) IS NULL FROM table;  -- detect all-null rows

或者你的情况:

SELECT ROW((_r).*) IS NULL;

相关:

  • NOT NULL constraint over a set of columns
  • Why is IS NOT NULL false when checking a row type?

Q2

  1. Is it possible to get serialized complex type without "empty" nested complex type?

是:

SELECT '(123,,)'::some_type;

或者:

SELECT (ROW(123, NULL, NULL))::some_type;

但是一旦你用这个赋值一个复合类型的plpgsql变量,而不是将嵌套的复合类型作为一个整体设置为NULL,每个嵌套的元素 设置为 NULL。

我测试中的最后一个函数 f_noparens() 证明了这一点。有人可能会说这是一个错误,我不会不同意...

SQL Fiddle 所有测试。