#function #postgresql #return-value
#функция #postgresql #возвращаемое значение
Вопрос:
Я новичок в postgresql, я могу написать несколько простых функций pg. Теперь у меня проблемы. Я хочу получить четыре столбца, используя регистр, когда, что мне делать?
Мой 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
Ответ №1:
Я чувствую себя вынужденным добавить еще один ответ. Я пока не удовлетворен теми, которые есть.
Попробуйте это:
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, это, вероятно, опечатка (?).
Ответ №2:
Я не уверен, правильно ли я понимаю, что вы сказали. Следующее — это просто тест.
--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)
Ответ №3:
Я думаю, вы хотите использовать 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;
Кстати, t.pirority
должно быть t.priority
или это реальное имя столбца?