从函数返回记录

时间:2017-05-15 13:11:43

标签: postgresql plpgsql

我尝试使用非常简单的测试功能在plpgsql中返回多个值。测试函数采用整数作为输入,如果它是正数,负数和零,则应该返回。我已经看到了一些例子,但它们都是复杂的并且过了我的脑袋。

以下是我尝试的内容:

create or replace function test(v integer)
returns record as $$

BEGIN

    IF v > 0
        THEN return true as positive, false as negative, false as zero;
    ELSEIF v < 0
        THEN return false as positive, true as negative, false as zero;
    ELSE 
        return false as positive, false as negative, true as zero;
    END IF;

END;
$$ LANGUAGE plpgsql;

还试过这个

create or replace function test(v integer)
returns record as $$

DECLARE 
    result record;

BEGIN

    IF v > 0
        THEN 
            result.positive = true;
            result.negative = false;
            result.zero = false;

    ELSEIF v < 0
        THEN 
            result.positive = false;
            result.negative = true;
            result.zero = false;
    ELSE 
            result.positive = false;
            result.negative = false;
            result.zero = true;
    return result;
    END IF;

END;
$$ LANGUAGE plpgsql;

也是这样:

IF v > 0
    THEN 
        SELECT true, false, false into
        result.positive, result.negative, result.zero;

ELSEIF v < 0
    THEN 
        SELECT false, true, false into
        result.positive, result.negative, result.zero;
ELSE 
        SELECT false, false, true into
        result.positive, result.negative, result.zero;
return result;
END IF;

3 个答案:

答案 0 :(得分:1)

我会按如下方式解决问题:

CREATE TYPE sign AS ENUM ('negative', 'zero', 'positive');

CREATE FUNCTION test(integer) RETURNS sign
   LANGUAGE sql IMMUTABLE STRICT AS
$$SELECT CASE
            WHEN $1 < 0
            THEN 'negative'
            WHEN $1 > 0
            THEN 'positive'
            ELSE 'zero'
         END::sign$$;

如果您想像示例中那样返回record,则必须使用ROW()构造函数从三个布尔值中创建单个复合值:

RETURN ROW(true, false, false);

但是这个解决方案有它的缺点:你不能在SQL中访问复合类型的各个字段,因为PostgreSQL在分析时不知道字段:

test=> SELECT test(42);
┌─────────┐
│  test   │
├─────────┤
│ (t,f,f) │
└─────────┘
(1 row)

test=> SELECT (test(42)).*;
ERROR:  record type has not been registered

test=> SELECT * FROM test(42);
ERROR:  a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM test(42);
                      ^

您必须在查询中指定记录定义:

test=> SELECT positive FROM test(42) test(positive boolean, negative boolean, zero boolean);
┌──────────┐
│ positive │
├──────────┤
│ t        │
└──────────┘
(1 row)

但是那种蔑视变量记录的目标。这就是为什么这些函数没有你引用的答案那么有用的原因。

答案 1 :(得分:1)

这将返回一条记录,因此结果将是(true,false,false)。

CREATE OR REPLACE FUNCTION test(v integer)
  RETURNS record AS $$

DECLARE 
    result record;

BEGIN
        SELECT true , false , false  into result;
return result;

END;

问题是结果未命名,因此您拥有此( true, false, false),并且您希望单独获取每个值。为此,您可以这样做:

select a, b, c from test(1) AS (a BOOL, b bool, c bool);

答案 2 :(得分:1)

这是对我有用的“返回多个值”问题的解决方案。

坦白说,WAAAAAY花了很长时间才找到解决这种普遍需求的解决方案!像OP一样,我所见过的大多数示例都过于复杂,令人费解。当然,我什至在寻找示例的唯一原因是因为the docs对此初学者尚不明确。希望这对某人有帮助。

将下面的代码粘贴到pgAdmin查询窗口中,选择一种调用解决方案,然后执行。

create or replace function receive_two_values() returns void language plpgsql as
$main$
declare
    returned record;
begin

    create or replace function return_two_arguments(
            arg1    text,
            arg2    text,
        out return1 text,
        out return2 text)
        language plpgsql as --"Returns record" is implied by multiple outs, so unnecessary here.
    $$
    begin
        return1 := arg1;
        return2 := arg2;
    end;
    $$;

    returned = return_two_arguments('Hello', 'World');
    raise notice 'return1="%"', returned.return1;
    raise notice 'return2="%"', returned.return2;

end;
$main$;

--Invoke in one of at least two ways:

--ONE:
    select receive_two_values();

--TWO:
    do language plpgsql
    $$
    begin
        perform receive_two_values();
    end;
    $$;


--Outputs:
--NOTICE:  return1="Hello"
--NOTICE:  return2="World"