这可行,但是我需要强制转换(::name_value_pair
)在我看来有点难看。有没有铸模的方法吗?
create type name_value_pair as (name text, value text);
create or replace function test1()
returns setof name_value_pair
as $$
begin
return next ROW('email', 'foo@example.com')::name_value_pair;
return next ROW('user_id', 'abc123')::name_value_pair;
return;
end;
$$ language plpgsql;
这是没有强制转换的错误。怎么不知道它是text
?我以为用引号引起来的字符串文字是text
,除非您将其转换为其他文字。
psql: ERROR: returned record type does not match expected record type
DETAIL: Returned type unknown does not match expected type text in column 1.
CONTEXT: PL/pgSQL function test1() line 4 at RETURN NEXT
选择:
=> select * from test1();
name | value
---------+-----------------
email | foo@example.com
user_id | abc123
我正在使用PostgreSQL 12 beta。
答案 0 :(得分:2)
函数中的问题是ROW构造函数“先罢工”,创建了两个 unknown 值的复合类型,对此没有隐式类型转换。
有 5种方法,无需使用显式强制转换 :
1。。仍在使用预定义的复合/行类型,并使用显式详细的语法(大部分是受教育的)。子选择将未知类型默认为text
,然后将它们组合为ROW类型:
CREATE OR REPLACE FUNCTION test1()
RETURNS SETOF name_value_pair AS
$func$
BEGIN
RETURN NEXT (SELECT t FROM (SELECT 'email', 'foo@example.com') t);
RETURN NEXT (SELECT t FROM (SELECT 'user_id', 'abc123') t);
END
$func$ LANGUAGE plpgsql IMMUTABLE;
SELECT * FROM test1();
2。。改用RETURNS TABLE
和RETURN QUERY
。无需形成复合类型,而让函数本身完成最后一步:
CREATE OR REPLACE FUNCTION test2()
RETURNS TABLE (name text, value text) AS
$func$
BEGIN
RETURN QUERY SELECT 'email', 'foo@example.com';
RETURN QUERY SELECT 'user_id', 'abc123';
END
$func$ LANGUAGE plpgsql IMMUTABLE;
SELECT * FROM test2();
3。或仍使用复合类型来定义返回类型。可能更适合您:
CREATE OR REPLACE FUNCTION test3()
RETURNS SETOF name_value_pair AS
$func$
BEGIN
RETURN QUERY SELECT 'email', 'foo@example.com';
RETURN QUERY SELECT 'user_id', 'abc123';
END
$func$ LANGUAGE plpgsql IMMUTABLE;
SELECT * FROM test3();
4。就这么简单,普通SQL函数中的普通VALUES
expression更短,更快:
CREATE OR REPLACE FUNCTION test4()
RETURNS SETOF name_value_pair AS
$func$
VALUES
('email', 'foo@example.com')
, ('user_id', 'abc123');
$func$ LANGUAGE sql IMMUTABLE;
SELECT * FROM test4();
5。或必须是PL / pgSQL:
CREATE OR REPLACE FUNCTION test5()
RETURNS SETOF name_value_pair AS
$func$
BEGIN
RETURN QUERY VALUES
('email', 'foo@example.com')
, ('user_id', 'abc123');
END
$func$ LANGUAGE plpgsql IMMUTABLE;
SELECT * FROM test5();
db <>提琴here
在 Postgres 10 中添加了针对函数的标量返回值的从unknown
到text
的隐式转换。 Postgres 9.6或更早的版本更加严格,对于替代项1-3会产生类似的错误。(仅功能4和5.在任何Postgres版本中均可使用。)
ERROR: structure of query does not match function result type DETAIL: Returned type unknown does not match expected type text in column 1.
人们可能会争论ROW类型仍然严格的行为是对该更新还是设计的疏忽。我猜可能是有理由的。
相关:
答案 1 :(得分:1)
这里的问题是像'email'这样的字符串常量的类型为unknown
,而不是类型为text
。
您可以这样重写示例:
create type name_value_pair as (name text, value text);
create or replace function test1()
returns setof name_value_pair
as $$
begin
return next ROW('email'::text, 'foo@example.com'::text);
return next ROW('user_id'::text, 'abc123'::text);
return;
end;
$$ language plpgsql;