Как я могу использовать случай, когда в функции postgresql - PullRequest
1 голос
/ 31 октября 2011

Я новичок в 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

Ответы [ 3 ]

2 голосов
/ 31 октября 2011

Я чувствую себя обязанным добавить еще один ответ. Я не доволен теми, кто до сих пор.
Попробуйте это:

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, это, вероятно, опечатка (?).

0 голосов
/ 31 октября 2011

Я не уверен, правильно ли я понимаю то, что вы сказали. Следующее - это всего лишь испытание.

--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)
0 голосов
/ 31 октября 2011

Я думаю, вы хотите использовать 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 или это реальное имя столбца?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...