Ошибка при создании хранимой процедуры в postgres - PullRequest
0 голосов
/ 15 апреля 2020

Я пытаюсь преобразовать хранимую процедуру oracle в Postgres функцию / процедуру.

Я провел некоторое исследование и прочитал много форумов, чтобы подготовить синтаксис для хранимой процедуры в postgres.

Но получаю ошибку для объявления целочисленной переменной.

Мой код подобен приведенному ниже: Цель моей процедуры - загрузить записи за один месяц в другой месяц (Пример: загрузить данные за январь 2020 года в Март 2020)

Postgres Процедура:

CREATE OR REPLACE FUNCTION Corporate.copy_forecast(code OUT integer, message OUT VARCHAR) 
        LANGUAGE plpgsql
    AS $$ 
DECLARE 
  v_current_month integer;
  v_previous_month integer;
begin 
  select max(cycleid) into v_previous_month,  max(cycleid)+1 into v_current_month from Corporate.forecast;

  INSERT INTO Corporate.forecast 
  (SELECT v_current_month,lob,delivery,forecast_val
   FROM Corporate.forecast 
   WHERE month= v_previous_month);

  code:=1;
  message:='Sucussfully loaded previous month forecast to current month';                                       
exception
  when others then 
  code:=0;
  message:='Failed';
END;
$$

Пожалуйста, помогите мне исправить вышеуказанную процедуру.

Ответы [ 2 ]

0 голосов
/ 16 апреля 2020

У вас нет проблем с объявлением целочисленной переменной, она намного больше, у вас структурные проблемы. Ниже я укажу эти проблемы, а затем покажу исправления. Индикатор "- << ..." обсуждает строку (и) чуть выше нее. </p>

CREATE OR REPLACE FUNCTION copy_forecast(code OUT integer, message OUT VARCHAR)  
--<< Improper format Should be  (out code integer, out message varchar) 
--<< and while not invalid IMHO bad design a function/procedure should just do its job correctly or raise an exception 

        returns ???    
--<< This is missing. A Postgres Function MUST declare what it returns, if nothing then RETURNS VOID. But I guess this was an Oracle Procedure.

        LANGUAGE plpgsql
    AS $$ 
DECLARE 
  v_current_month integer;
  v_previous_month integer;
begin 
  select max(cycleid) into v_previous_month,  max(cycleid)+1 into v_current_month from  forecast;
  --<< Invalid format Should Be select var1,var2 into local1, local2 ...

  INSERT INTO  forecast                 
  --<< Very dangerous. If table ever changes this will fail.
  (SELECT v_current_month,lob,delivery,forecast_val
   FROM  forecast 
   WHERE month= v_previous_month);

  code:=1;
  message:='Successfully loaded previous month forecast to current month';                                       
exception
  when others then                     
  code:=0;
  message:='Failed'
--<< Very dangerous (all 3 lines). When an error occurs you will never know what it is. See insert above 
;
END;
$$;

Следующее исправляет ошибки, указанные выше. Снова индикатор (- *) обсудил строку (и) над ним.

create or replace function copy_forecast()   
        returns boolean                    
        language plpgsql
    as $$ 
declare 
  v_current_month integer;
  v_previous_month integer;
begin 
  select max(cycleid)
       , max(cycleid)+1   
    into v_previous_month
       , v_current_month
    from forecast;

  insert into forecast (cycleid,lob,delivery,forcast_val )                
       select v_current_month,lob,delivery,forecast_val 
         from forecast 
        where month= v_previous_month); 
  --* insert will fail I cannot resolve. MONTH not inserted, but must exist on table.
  --* It seems you are using cycleid and month as synonyms   


  return True;
  --* you can leave the out parameters if desirded. Set them before the return
exception
  when others then                      
       -- Log the error and debug information here
       return false;
       --* you can leave out parameters if desired Set them before the return.       
end;

Это должно исправить проблемы со структурой в вашей функции. Однако логическая проблема с month / cycleid остается. Тем не менее, это не дает вам цели Как уже говорилось, «цель моей процедуры - загрузить месячные записи в другой месяц (например: загрузить данные за январь 2020 года в март 2020 года»). Эта функция не может сделать это. Он может копировать только последний месяц / cycleid в следующий месяц / cycleid; так январь-> февраль, февраль-> март, ... ноя-> де c. Но De c -> Jan потерпит неудачу, если month / cycleid не будет 13, и последующие месяцы продолжат увеличиваться месяц / цикл. Для достижения вашей цели необходимы входные параметры для источника (от) и цели (до). И, как сказал @LaurenzAlbe, «нет движущихся целей». Это был бы другой вопрос.

0 голосов
/ 15 апреля 2020

Есть несколько проблем с вашим кодом:

  • Первая проста: вы говорите LANGUAGE sql, но вы пишете код PL / pg SQL.
    Это объясняет сообщение об ошибке, которое вы получаете. Используйте LANGUAGE plpgsql, если вы хотите написать PL / pg SQL.

  • Вы используете переменные, которые совпадают с именами столбцов, что приводит к неоднозначности. Например, вы объявляете

    current_month integer;
    previous_month integer;
    

    , но у вас есть WHERE предложение

    WHERE current_month = previous_month
    

    , где очевидно, что один из них должен ссылаться на переменную, а другой - на столбец таблицы. Это не сработает и приведет к ошибкам.

    • Лучшее и простое решение - всегда использовать имена переменных, отличающиеся от имен столбцов. Простой способ - начать все имена переменных с v_.

    • Второй вариант - всегда указывать столбцы с именем таблицы и переменные с именем функции.

...