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

时间:2015-04-17 23:45:20

标签: sql postgresql null row plpgsql

我的复杂类型包含另一个复杂类型的单个字段:

-- 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. 是否可以获得序列化的复杂类型而不使用"空"嵌套复杂类型?

    -- 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,,)
    
  3. 我正在运行PostgreSQL 9.4.0,由Visual C ++ build 1800,64位(Windows 7)编译。

1 个答案:

答案 0 :(得分:0)

Q1

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

你不是第一个被这个困惑的人。对于简单类型IS NULLIS NOT NULL是反向操作。要么是一个是真的,要么是另一个。但对于行值或复合(复杂)类型则不然。如果(且仅当)每一列都为IS NOT NULLTRUE仅返回NOT NULLPer documentation:

  

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

大胆强调我的。

但复杂类型是用NULL初始化的!

嗯,不是完全。复合类型使用所有嵌套的元素 NULL进行初始化,对于嵌套复合类型也是如此。包含包含任何的复合类型的复合类型不会被视为NULL整体。相当混乱......

有一种解决方法:row-wise comparisoncomposite 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;

相关:

Q2

  
      
  1. 是否可以获得没有“空”嵌套复杂类型的序列化复杂类型?
  2.   

是:

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

或者:

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

只要为此分配复合类型的plpgsql变量,而不是将嵌套复合类型设置为NULL,每个嵌套的元素都设置为NULL。

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

SQL Fiddle进行所有测试。