我将以下函数存储在 Postgres 15 数据库中。
我使用 dbeaver 连接数据库。
CREATE OR REPLACE FUNCTION schema_name.function_name(
in input_user_id int2
)
RETURNS TABLE(
column_1 smallint,
column_2 character varying,
column_3 character varying,
column_4 timestamp with time zone,
column_5 timestamp with time zone,
column_6 character varying,
column_7 int2,
column_8 int2
)
LANGUAGE plpgsql
AS $function$
begin
return query
select *
from schema_name.table_name
where table_name.column_5 = input_user_id;
end;
$function$
;
如果我直接在 dbeaver 上运行查询部分,我会得到预期的结果
select * from schema_name.table_name where column_5 = 1;
如果我运行该函数,我会收到错误
select * from schema_name.function_name(1);
SQL Error [42883]: ERROR: function schema_name.function_name(integer) does not exist Hint: No function matches the given name and argument types. You might need to add explicit type casts. Position: 15
select * from schema_name.function_name(int2 '1');
或
select * from schema_name.function_name(1::int2);
或
select * from schema_name.function_name(1::smallint);
SQL Error [42804]: ERROR: structure of query does not match function result type Detail: Returned type text does not match expected type smallint in column 7. Where: SQL statement "select * from schema_name.table_name where table_name.column_5 = input_user_id" PL/pgSQL function schema_name.function_name(smallint) line 3 at RETURN QUERY
我也将类型转换为整数并遇到另一个错误。
我做错了什么?
注意,由于错误提到了特定列,我添加了完整的列列表,但我没有编辑错误消息。
没有从
int4
→ int2
进行隐式转换(有充分的理由)。因此,您必须传递实际的 int2
(int2 '1'
) 或无类型字符串文字 ('1'
)。详细评估和更多选择:
更多问题:
smallserial
不是实际的数据类型。您必须在 int2
中使用 smallint
(又名 RETURNS TABLE
)。参见:
当函数返回列列表时,请勿使用
SELECT *
。使用匹配的 SELECT
列表。
使用表别名并对可能与
OUT
参数冲突的所有列名称进行表限定。 (RETURNS TABLE
中列出的所有列都是有效的OUT
参数。)
这会起作用:
CREATE OR REPLACE FUNCTION schema_name.function_name(input_user_id int2)
RETURNS TABLE (
column_1 int2 -- makes no sense: smallserial
, column_2 varchar
, column_3 timestamptz
, column_4 varchar
, column_5 int2
)
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY
SELECT t.column_1, t.column_2, t.column_3, t.column_4, t.column_5
FROM schema_name.table_name t
WHERE t.column_5 = input_user_id;
END
$func$;
致电:
SELECT * FROM schema_name.function_name('1');
如果您确实想返回
schema_name.table_name
定义的整行,请使用 RETURNS SETOF schema_name.table_name
代替。 现在可以在函数体中使用SELECT *
了。此外,更少的命名冲突:
CREATE OR REPLACE FUNCTION schema_name.function_name(input_user_id int2)
RETURNS SETOF schema_name.table_name
LANGUAGE sql AS
$func$
SELECT *
FROM schema_name.table_name
WHERE column_5 = input_user_id;
$func$;
还演示了一个更简单的 SQL 函数,它可以完成简单的工作。