基本的东西,如C数据类型中的结构,存在于所有流行的语言中,并且期望这些语言的函数也可以返回结构…并且,根据正交性原则,期望您可以访问返回的结构项。
然而,PostgreSQL不提供对FUNCTION ... RETURNS RECORD
的结构项的访问。是正确的吗?但是程序员使用PostgreSQL毫无怨言…有一个简单直观的解决方案吗?
类似问题:PostgreSQL v9。X有真实的记录数组吗?
典型案例说明
CREATE FUNCTION foo(int) RETURNS RECORD AS $$
SELECT $1 as a, 'Hello #'||$1 as b;
$$ LANGUAGE SQL;
SELECT foo(6); -- works, but I need only one item
访问SQL上下文中的记录项:
SELECT (foo(6)).a; -- NOT works (but no ambiguity!)
-- For syntax discussion:
WITH f AS (SELECT foo(6) as r) SELECT r.a FROM f; -- NOT works
-- ambiguous syntax; confused r with table, in "f.r.a", f with schema
-- perhaps r['a'] would be a good syntax solution
访问PLpgSQL上下文中的记录项:
怎么说x:=(foo(6)).a
或y:=foo(6); x:=y.a
?现在有一些预期的行为,在PLpgSQL中,至少命名为"记录"。是允许的:
CREATE FUNCTION bar() RETURNS text AS $F$
DECLARE
tmp record;
s text;
BEGIN
-- s:=(foo(7)).b; NOT WORKS, is like an "anonymous record" (not permitted)
tmp := foo(6);
s:=tmp.b; -- IT WORKS!! is like a "named record" (permitted)
RETURN s||'! '||tmp.a; -- ...works accessing any other individual itens
END;
$F$ LANGUAGE plpgsql IMMUTABLE;
是否简单直观?
select a
from foo(6) s(a int, b text);
如果您使用更灵活的returns table
而不是(有点过时的)returns record
,那么事情变得非常容易:
CREATE FUNCTION foo(int) RETURNS table (a int, b text)
AS
$$
SELECT $1 as a, 'Hello #'||$1 as b;
$ LANGUAGE SQL;
现在你可以使用:
select b
from foo(6);
如果你关心的是"表"vs。"records",您还可以定义type
来克服额外的结果集定义:
create type foo_return as (a int, b text);
CREATE FUNCTION foo(int) RETURNS foo_return
AS
$$
SELECT $1, 'Hello #'||$1;
$$ LANGUAGE SQL;
你仍然可以选择上面的选项:
select b
from foo(6);
第三种可能更像C的方法是使用out参数(如手册中所示)
CREATE FUNCTION foo(p1 int, out a int, out b text)
AS
$$
SELECT $1, 'Hello #'||$1;
$$
LANGUAGE SQL;
那么你就不需要from
:
select (foo(1)).b;