我是postgresql的新手,我可以编写一些简单的pg函数。现在我遇到了麻烦。 我想用case来获取四列,我该怎么办?
我的sql:
CREATE OR REPLACE FUNCTION get_grade(IN integer, out integer,out integer,out integer,out integer) AS
$BODY$
begin
select
sum(case when t.pirority = 66 then 1 else 0 end) as I ,
sum(case when t.pirority = 67 then 1 else 0 end) as II,
sum(case when t.pirority = 68 then 1 else 0 end) as III,
sum(case when t.pirority = 225 then 1 else 0 end) as IIII
from dt_info t
where t.registrant = $1
end
$BODY$
LANGUAGE 'plpgsql' VOLATILE
当我使用
时select * from get_grade(22);
它没有按预期工作。
CREATE OR REPLACE FUNCTION get_grade(IN integer) returns setof record AS
$BODY$
select
sum(case when t.pirority = 66 then 1 else 0 end) as I,
sum(case when t.pirority = 67 then 1 else 0 end) as II,
sum(case when t.pirority = 68 then 1 else 0 end) as III,
sum(case when t.pirority = 225 then 1 else 0 end) as IIII
from dt_info t
where t.registrant = $1
$BODY$
LANGUAGE 'sql' VOLATILE;
然后我执行它:
select * from get_grade(25) as (v1 integer, v2 integer, v3 integer, v4 integer)
发生错误:
ERROR: function return row and query-specified return row do not match
答案 0 :(得分:2)
我觉得有必要再加上一个答案。到目前为止,我对这些不满意 试试这个:
CREATE OR REPLACE FUNCTION get_grade(integer)
RETURNS TABLE (
i int4
,ii int4
,iii int4
,iiii int4) AS
$BODY$
SELECT sum(case when t.priority = 66 then 1 else 0 end)::int4 -- as I
,sum(case when t.priority = 67 then 1 else 0 end)::int4 -- as II
,sum(case when t.priority = 68 then 1 else 0 end)::int4 -- as III
,sum(case when t.priority = 225 then 1 else 0 end)::int4 -- as IIII
FROM dt_info t
WHERE t.registrant = $1;
$BODY$
LANGUAGE sql;
您可以使用LANGUAGE plpgsql
编写这样的简单查询。您也可以使用LANGUAGE sql
。无论哪种方式都有一定的优势。我在这里使用了sql
。不需要使用sql
或plpgsql
字样的引号。
不带引号的大写标识符是PostgreSQL中的错误样式。无论如何,它们都折叠成小写,只会让人感到困惑。
函数体内的列别名在外部不可见。在这种情况下,它们只能作为文档。您必须明确命名您的OUT参数才能获得结果集的列名。否则,您必须为每个呼叫指定列列表。我不会这样做。
OUT参数的名称与函数体中的其他名称共享名称空间。表限定了与OUT参数冲突的列名。不要使用会冲突的别名。我在这里替换你的别名评论。
返回列的类型必须与标头中的声明完全匹配。 sum()返回bigint 。您必须明确强制转换为整数或收到错误消息。
我使用了列名priority
而不是pirority
。正如@Mu所指出的,这可能是一个错字(?)。
答案 1 :(得分:0)
我认为您想要使用RETURN QUERY
和setof record
返回类型:
CREATE OR REPLACE FUNCTION get_grade(IN integer, out bigint, out bigint, out bigint, out bigint)
returns setof record AS
$BODY$
begin
return query select
sum(case when t.pirority = 66 then 1 else 0 end) as I,
sum(case when t.pirority = 67 then 1 else 0 end) as II,
sum(case when t.pirority = 68 then 1 else 0 end) as III,
sum(case when t.pirority = 225 then 1 else 0 end) as IIII
from dt_info t
where t.registrant = $1;
end
$BODY$
LANGUAGE plpgsql VOLATILE;
您可以将其作为纯SQL函数执行:
CREATE OR REPLACE FUNCTION get_grade(IN integer, out bigint, out bigint, out bigint, out bigint)
returns setof record AS
$BODY$
select
sum(case when t.pirority = 66 then 1 else 0 end) as I,
sum(case when t.pirority = 67 then 1 else 0 end) as II,
sum(case when t.pirority = 68 then 1 else 0 end) as III,
sum(case when t.pirority = 225 then 1 else 0 end) as IIII
from dt_info t
where t.registrant = $1;
$BODY$
LANGUAGE sql VOLATILE;
BTW,t.pirority
应该是t.priority
还是真正的列名?
答案 2 :(得分:0)
我不确定如果我理解你说的很好。以下只是一个测试。
--create table
skytf=> create table grade (registrant integer, pirority integer);
CREATE TABLE
skytf=> insert into grade values (1,66);
INSERT 0 1
skytf=> insert into grade values (1,66);
INSERT 0 1
skytf=> insert into grade values (1,67);
INSERT 0 1
skytf=> insert into grade values (1,67);
INSERT 0 1
skytf=> insert into grade values (1,67);
INSERT 0 1
skytf=> insert into grade values (1,68);
INSERT 0 1
skytf=> insert into grade values (1,225);
INSERT 0 1
skytf=> insert into grade values (1,225);
INSERT 0 1
skytf=> insert into grade values (1,225);
INSERT 0 1
skytf=> insert into grade values (1,225);
INSERT 0 1
skytf=> select * from grade;
registrant | pirority
------------+----------
1 | 66
1 | 66
1 | 67
1 | 67
1 | 67
1 | 68
1 | 225
1 | 225
1 | 225
1 | 225
--create function
CREATE OR REPLACE FUNCTION get_grade( in_reg integer ) RETURNS RECORD AS
$$
DECLARE
g_user record;
BEGIN
select
sum(case when t.pirority = 66 then 1 else 0 end) as I ,
sum(case when t.pirority = 67 then 1 else 0 end) as II,
sum(case when t.pirority = 68 then 1 else 0 end) as III,
sum(case when t.pirority = 225 then 1 else 0 end) as IIII
into g_user
from grade t
where t.registrant = in_reg;
return g_user;
END;
$$
LANGUAGE PLPGSQL;
--execute function
skytf=> select get_grade(1);
get_grade
-----------
(2,3,1,4)
(1 row)