是否有可能让PostgreSQL函数返回“任意”类型?

时间:2012-02-06 15:31:27

标签: sql database postgresql

是否可以为某些PostgreSQL函数定义任意返回类型?

这个想法是,根据呼叫,输出可能会以不同的方式返回。

例如,假设我们有:

TypeA : (name, email)
TypeB : (name, email, address, phone)

我们可能有一个功能:

func1(name varchar);

但返回类型可以是:TypeATypeB

那么,是否可以定义func1,以便任意返回类型有效?

修改

如果解决方案是 refcursor ...有人可以根据我的问题中的示例写一个答案吗?这会有很大的帮助!

1 个答案:

答案 0 :(得分:3)

您有几个选择。第一种是使用将在调用时强制转换的多态类型,第二种是使用强制转换,第三种是返回refcursor。

多态类型

在这种情况下,您可以执行以下操作:

 CREATE FUNCTION foo (bar varchar, baz ANYELEMENT) returns ANYELEMENT AS
 $$
   SELECT 'test'::TEXT;
 $$ language sql;

然后调用它,你会在调用时转换NULL参数:

SELECT * FROM foo('test', null::varchar);

你遇到的真正问题是你必须在每次通话时指定一个类型。

带投射的单一返回类型

在您的示例中,一种类型具有另一种类型的字段子集。所以你可以:

CREATE TYPE all_info AS (
   name text,
   email text,
   address text,
   phone text
);
CREATE TYPE email_only AS (
   name text,
   email text
);
CREATE FUNCTION email_only(all_info) returns email_only LANGUAGE SQL IMMUTABLE AS $$
SELECT $1.name, $1.email;
$$;
CREATE CAST (all_info as email_only) WITH FUNCTION email_only(all_info);

然后你创建你的函数来返回all_info,你可以在输出上进行转换。类似的东西:

SELECT (f::email_only).* FROM my_function('foo') f;

请注意,这两个允许您使用SQL语言函数,而reframeors则不会这样做。

<强> REFCURSOR

在这种情况下,您必须使用plpgsql

CREATE OR REPLACE FUNCTION foo(bar varchar) RETURNS refcursor LANGUAGE plpgsql AS
$$
DECLARE a REFCURSOR;
BEGIN
   OPEN a FOR SELECT ....;
   RETURN a;
END;
$$;

总的来说,我认为从超集和演员方法开始比其他方式更容易。反射器可能是第二种方法。最后一个是坚持一个类型的演员。