我认为这在 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.) 使用 recursors 的可能解决方案:
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 错误。也许我把名字设置错了,我不知道,我认为这不值得付出更多的努力。