问题
Basic things as struct in C data types, exist in all popular languages, and is expected that functions, of these languages, also can return a struct... And, by an orthogonality principle, is expected you can access the returned struct itens.
PostgreSQL, nevertheless, did not offer access to the struct itens of a FUNCTION ... RETURNS RECORD
. It is correct?
But programmers use PostgreSQL without complaining... There are a simple and intuitive workaround?
Similar question: PostgreSQL v9.X have real "array of record"?
Illustrating by typical cases
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
Access of record itens in a SQL context:
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
Access of record itens in a PLpgSQL context:
How to say x:=(foo(6)).a
or y:=foo(6); x:=y.a
? Now there are some expected behaviuor, in PLpgSQL, at least "named record" is permitted:
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;
回答1:
If you use the more flexible returns table
instead of (the somewhat outdated) returns record
, then things get really easy:
CREATE FUNCTION foo(int) RETURNS table (a int, b text)
AS
$$
SELECT $1 as a, 'Hello #'||$1 as b;
$ LANGUAGE SQL;
now you can use:
select b
from foo(6);
If you are concerned about "tables" vs. "records" you can also define a type
to overcome the additional result set definition:
create type foo_return as (a int, b text);
CREATE FUNCTION foo(int) RETURNS foo_return
AS
$$
SELECT $1, 'Hello #'||$1;
$$ LANGUAGE SQL;
You can still the above select then:
select b
from foo(6);
A third maybe more "C" like approach would be to use out parameters (as shown in the manual)
CREATE FUNCTION foo(p1 int, out a int, out b text)
AS
$$
SELECT $1, 'Hello #'||$1;
$$
LANGUAGE SQL;
Then you don't need a from
:
select (foo(1)).b;
回答2:
Is this simple and intuitive?
select a
from foo(6) s(a int, b text);
来源:https://stackoverflow.com/questions/23439240/functions-can-not-to-return-individual-items-of-a-record-is-it-any-workaround