我认为这在 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 客户端获取了字符串中的每一列,所以列类型定义对我来说毫无用处......这个解决方案如果没有列类型定义是最好的,但它不可接受。
可以用这个类似于table:
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 本身,但这是不可接受的,因为我不能将它用作普通变量,我必须给出一个字符串作为游标名称......顺便说一句我没有设法使用refcursor 本身作为 phpstorm 的结果。我得到 jdbc cursor not found 错误。可能是我把名字弄错了,我不知道,我觉得不值得再努力。