Как я могу использовать регистр, когда в функции postgresql

#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 или это реальное имя столбца?