Создать функцию или хранимый процесс с интервальной переменной

#sql #postgresql

#sql #postgresql

Вопрос:

Я новичок в PostgreSQL, но уже много лет работаю с MSSQL. В настоящее время я работаю с PostgreSQL 13.

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

Я пытаюсь создать что-то подобное в PostgreSQL. У меня есть некоторый код, работающий, чтобы делать то, что я хочу. Однако сейчас я пытаюсь написать функцию или хранимую процедуру для автоматизации этого кода. У меня возникают проблемы с преобразованием кода для работы в функции или хранимой процедуре.

Мой код, над которым я работаю, выглядит следующим образом. Это очень урезанная версия кода для иллюстрации.

 DO $$
    DECLARE daydiff INTERVAL;
    DECLARE startdate DATE;
    DECLARE enddate DATE;
    DECLARE fiscalstartdate DATE;
BEGIN
    -- Populate these variables
    startdate:=(date '2017-01-01');
    enddate:=(date '2017-12-31');
    fiscalstartdate:=(date '2016-09-01');

    -- Calculate date diff
    daydiff:=make_interval(days => startdate - fiscalstartdate);
    
    -- Insert records into table
    INSERT INTO master.Calendar (
        full_date
        , year
        , fiscal_year
    )
    SELECT
        CAST(generate_series AS date) AS full_date
        , EXTRACT(YEAR FROM generate_series)::INTEGER AS year
        , EXTRACT(YEAR FROM generate_series   daydiff)::INTEGER AS fiscal_year
    FROM (
        SELECT generate_series(
            startdate::timestamp,
            enddate::timestamp,
            interval '1 days'
        )
    ) a;

END $$;
  

Он делает именно то, что я хочу сделать. Однако я хочу иметь возможность вызывать это в функции или хранимой процедуре для автоматизации перестройки таблиц и данных. Затем я попробовал несколько разных вещей, но сейчас я нахожусь вот в чем. Опять же, это урезанная версия, но проблема все еще присутствует.

 CREATE OR REPLACE PROCEDURE create_calendar_table(startdate DATE, enddate DATE, fiscalstartdate DATE) AS $$ 
DECLARE 
    daydiff INTERVAL;
BEGIN
    -- Calculate date diff
    daydiff:=make_interval(days => startdate - fiscalstartdate);
    
    -- Insert records into table
    INSERT INTO master.Calendar (
        full_date
        , year
        , fiscal_year
    )
    SELECT
        CAST(generate_series AS date) AS full_date
        , EXTRACT(YEAR FROM generate_series)::INTEGER AS year
        , EXTRACT(YEAR FROM generate_series   daydiff)::INTEGER AS fiscal_year
    FROM (
        SELECT generate_series(
            startdate::timestamp,
            enddate::timestamp,
            interval '1 days'
        )
    ) a;

END $$ LANGUAGE SQL;
  

Я получаю сообщение об ошибке «синтаксическая ошибка на «ИНТЕРВАЛЕ» или рядом с ним». Я пробовал несколько вещей, например, пытался добавить туда DO $$, и это, похоже, вообще не сработало. Очень хорошо может быть мое невежество в этой версии SQL. Лучшее, что я могу сказать, это то, что я не могу объявить тип ИНТЕРВАЛА при создании процедуры или функции, как я могу в DO $$ .

Как я могу обойти это или как правильно это сделать в PostgreSQL? Любая помощь приветствуется.

Комментарии:

1. Не связано, но: declare запускает блок, вам нужно использовать его только один раз для всех переменных, а не по одной для каждой переменной.

2. Спасибо, это полезно знать. Я ценю вашу помощь.

Ответ №1:

Вам нужно language plpgsql — вы не можете использовать переменные внутри функции SQL.

Комментарии:

1. Я не понимал, что там может быть несколько языков, которые можно использовать. Это интересно . Мне нужно будет прочитать об этом подробнее. Еще раз спасибо за вашу помощь.

2. @Kupokev postgresql.org/docs/current/xplang.html