我的复杂类型包含另一个复杂类型的单个字段:
-- 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)编译。
答案 0 :(得分:0)
- 是否可以使用嵌套复杂类型测试复杂类型的空值?
醇>
你不是第一个被这个困惑的人。对于简单类型IS NULL
和IS NOT NULL
是反向操作。要么是一个是真的,要么是另一个。但对于行值或复合(复杂)类型则不然。如果(且仅当)每一列都为IS NOT NULL
,TRUE
仅返回NOT NULL
。 Per documentation:
注意:如果表达式是行值,则
IS NULL
为真时 行表达式本身为null或当所有行的字段为空时, 当行表达式本身为非null时,IS NOT NULL
为真 并且所有行的字段都是非空的。由于此行为,IS NULL
和IS NOT NULL
并不总是返回反向结果 行值表达式,即包含的行值表达式 对于两个测试,NULL和非空值都将返回false。这 定义符合 SQL标准 [...]
大胆强调我的。
但复杂类型是用NULL初始化的!
嗯,不是完全。复合类型使用所有嵌套的元素 NULL进行初始化,对于嵌套复合类型也是如此。包含包含任何的复合类型的复合类型不会被视为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;
相关:
- 是否可以获得没有“空”嵌套复杂类型的序列化复杂类型?
醇>
是:
SELECT '(123,,)'::some_type;
或者:
SELECT (ROW(123, NULL, NULL))::some_type;
但只要为此分配复合类型的plpgsql变量,而不是将嵌套复合类型设置为NULL,每个嵌套的元素都设置为NULL。
我的测试f_noparens()
中的最后一个函数证明了这一点。有人可能会说这是一个错误,我不会反对......
SQL Fiddle进行所有测试。