我得到了Postgresql 8.4
我有一个用户表
user_id INT,
user_name VARCHAR(255),
user_email VARCHAR(255),
user_salt VARCHAR(255)
和2个功能:
一个SETOF
:
CREATE FUNCTION test ()
RETURNS SETOF "user"
AS
$BODY$
BEGIN
RETURN QUERY SELECT
*
FROM
"user";
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
一个TABLE
:
CREATE FUNCTION test ()
RETURNS TABLE (id INT, name VARCHAR, email VARCHAR)
AS
$BODY$
BEGIN
RETURN QUERY SELECT
"user".user_id, "user".user_name, "user".user_email
FROM
"user";
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
按SETOF
自动填充列类型,但我无法设置列名以及在结果中选择的列。到TABLE
我可以切断user_
前缀并设置确切的列名,但我必须手动设置列类型。
是否有可能获得两者的优势?
答案 0 :(得分:2)
PostgreSQL中的类型处理(以及一般的SQL)是严格的。定义函数的RETURN
类型可能很棘手
有简单的解决方案与纯SQL :
选择并重命名所有列:
SELECT * FROM t AS t(id, name, email, salt);
选择并重命名一些列:
SELECT user_id AS id, user_name AS name FROM t;
如果由于某种原因需要服务器端功能,您仍然可以将这些SQL功能与功能结合使用。给出一个表格t
,就像你的问题和这个简单的函数一样:
CREATE OR REPLACE FUNCTION f_test()
RETURNS SETOF t AS
$func$
SELECT * FROM t -- do stuff here
$func$ LANGUAGE sql STABLE;
仅重命名列(无需提供类型):
SELECT * FROM f_test() t(id, name, email, salt)
选择并重命名一些列:
SELECT user_id AS id, user_name AS name FROM f_test() t;
您可以将它与不同表格上的各种不同功能结合起来:
Refactor a PL/pgSQL function to return the output of various SELECT queries
但我不完全确定你想要解决哪个问题。
永远不要引用语言名称。 plpgsql
是一个标识符。 Quoting can lead to unexpected problems
只能从表中选择的函数可以是declared STABLE
。嵌套时重复调用可能会有所帮助。
一般来说,我建议升级到Postgres的当前版本。 8.4 is rather old and will be lose support in less than a year。自8.4以来,该领域已有许多改进。
答案 1 :(得分:1)
我不认为这在pl / pgsql中是可行的,因为它强烈依赖于用户定义的类型。可悲的是,这种语言对于类型自动检测还不够聪明...我认为我将使用的第一个可能的解决方案,它解决了部分问题,因为至少我不需要通过表格列的类型更改手动重构每个函数强>
1。)询问列类型的可能解决方案:
CREATE FUNCTION test ()
RETURNS TABLE (id "user".user_id%TYPE, name "user".user_name%TYPE, email "user".user_email%TYPE)
AS
$BODY$
BEGIN
return QUERY SELECT
"user".user_id, "user".user_name, "user".user_email
FROM
"user";
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
至少这种类型不是多余的。不是最好的,但可以接受。
2.使用SETOF RECORD的可能解决方案:
CREATE FUNCTION test ()
RETURNS SETOF RECORD
AS
$BODY$
BEGIN
RETURN QUERY SELECT
"user".user_id AS id, "user".user_name AS name, "user".user_email AS email
FROM
"user";
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
没有列类型定义列表,我收到以下错误:
错误:返回函数需要列定义列表 “记录”
所以我必须像这样使用它:
SELECT * FROM test() AS (id INT, name VARCHAR, email VARCHAR);
而不是:
SELECT * FROM test()
我通过php客户端获取字符串中的每一列,因此列类型定义对我来说无用......这种解决方案在没有列类型定义的情况下是最好的,但是不可接受。
可以使用类似于表格的表格:
CREATE FUNCTION test (OUT id "user".user_id%TYPE, OUT name "user".user_name%TYPE, OUT email "user".user_email%TYPE)
RETURNS SETOF RECORD
AS
$BODY$
BEGIN
RETURN QUERY SELECT
"user".user_id, "user".user_name, "user".user_email
FROM
"user";
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
例如,我可以将所有内容设置为TEXT:
CREATE FUNCTION test (OUT id TEXT, OUT name TEXT , OUT email TEXT )
RETURNS SETOF RECORD
AS
$BODY$
BEGIN
RETURN QUERY SELECT
"user".user_id::TEXT , "user".user_name::TEXT , "user".user_email::TEXT
FROM
"user";
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
这有效,但这远不是类型自动检测,它会导致很多冗余的文本转换器代码......
3.。)使用refcursors的可能解决方案:
CREATE FUNCTION test ()
RETURNS SETOF "user"
AS
$BODY$
DECLARE
refc "user";
BEGIN
FOR refc IN
SELECT
"user".user_id, "user".user_name, "user".user_email
FROM
"user"
LOOP
RETURN NEXT refc;
END LOOP ;
RETURN ;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
这填补了缺少列的空值,我无法命名列,而且sql循环非常慢......所以这是不可接受的。
通过refcursors还有另一种方法:返回refcursor本身,但它是不可接受的,因为我不能将它用作普通变量,我必须给一个字符串作为游标名称...顺便说一句我没有设法使用refgsrsor本身就是phpstorm的结果。我找到了jdbc cursor not found错误。也许我把名字设置错了,我不知道,我认为这不值得付出更多的努力。