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

Posted

技术标签:

【中文标题】具有另一个复杂类型的字段的复杂类型中的空检测【英文标题】:Null detection in a complex type with field of another complex type 【发布时间】:2015-04-17 23:45:19 【问题描述】:

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

-- 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

    是否可以用嵌套的复杂类型测试复杂类型的空值?

    是否可以在没有“空”嵌套复杂类型的情况下获得序列化复杂类型?

    -- 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 位 (Windows 7)。

【问题讨论】:

【参考方案1】:

第一季度

    是否可以用嵌套的复杂类型测试复杂类型的空值?

您不是第一个对此感到困惑的人。对于简单类型IS NULLIS NOT NULL 是逆运算。要么是真的,要么是另一个。但对于行值或复合(复杂)类型则不然。 IS NOT NULL 仅当(且仅当)每一列都是 NOT NULL 时才返回 TRUE。 Per documentation:

注意:如果表达式是行值的,那么IS NULL 在 行表达式本身为空或当所有行的字段为空时, 而IS NOT NULL 在行表达式本身为非空时为真 并且所有行的字段都是非空的。由于这种行为,IS NULLIS NOT NULL 并不总是返回相反的结果 行值表达式,即 包含 对于这两个测试,NULL 和非 null 值都将返回 false。 这 定义符合 SQL 标准 [...]

我的大胆强调。

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

嗯,不完全是。复合类型使用所有嵌套的 elements NULL 初始化,递归嵌套复合类型也是如此。并且复合类型包含 复合类型包含anything 不被认为是一个整体的NULL。相当混乱...

有一种方法可以解决这个问题:row-wise comparison 与 composite type comparison 略有不同。您可以从分解的类型构造一行并使用IS NULL 进行测试。这可以满足您的需求。 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? Delete duplicate rows from table with no unique key

第二季度

    是否可以在没有“空”嵌套复杂类型的情况下获得序列化复杂类型?

是的:

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

或者:

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

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

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

SQL Fiddle 进行所有测试。

【讨论】:

很棒的答案!谢谢!

以上是关于具有另一个复杂类型的字段的复杂类型中的空检测的主要内容,如果未能解决你的问题,请参考以下文章

ATL/COM 中的 IDL:我可以发布复杂类型的 const 吗?

如何使用 INSERT-SELECT 查询加载具有复杂数据类型的 Hive 表

EF6:代码优先复杂类型

Hive 中的复杂数据类型问题

Hive复杂数据类型:array、map、struct

将属性添加到简单类型或限制到 Xml 架构中的复杂类型