Как правильно использовать оператор DECLARE в функции plpgsql. ОШИБКА: запрос не имеет назначения для результирующих данных

#sql #postgresql #plpgsql

#sql #postgresql #plpgsql

Вопрос:

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

Чтобы получить результат, я создал ТИП и применил несколько операторов INNER JOIN

Когда я вызываю функцию, я получаю следующее

 ERROR:  query has no destination for result data
HINT:  If you want to discard the results of a SELECT, use PERFORM instead.
 

Вот мой код:

УСТАНОВИТЕ search_path на olympic;

 CREATE OR REPLACE FUNCTION fn_get_info_by_sponsor
       (register_date tb_register.register_ts%type, sponsor_name tb_sponsor.name%type)
RETURNS SETOF sponsor_data AS $
DECLARE 
 data_sponsor sponsor_data;
 email  olympic.email_type;
 sponsor_name tb_finance.sponsor_name%type;
 athlete_name tb_athlete.name%type;
 discilpine_name tb_discipline.name%type;
 round_number  tb_register.round_number%type;
 mark tb_register.register_measure%type;
 register_position tb_register.register_position%type;
 register_date  tb_register.register_ts%type;
 BEGIN 
      SELECT 
           tb_finance.sponsor_name,
           tb_sponsor.email email_type,
           tb_athlete.name AS athlete_name,
           tb_discipline.name AS discipline_name,
           tb_register.round_number,
           tb_register.register_measure,
           tb_register.register_position,
           tb_register.register_ts
      INTO  data_sponsor
      FROM  olympic.tb_sponsor
           
      INNER JOIN olympic.tb_finance

           ON (tb_finance.sponsor_name = tb_sponsor.name)

      INNER JOIN olympic.tb_athlete

           ON tb_athlete.athlete_id = tb_finance.athlete_id

      INNER JOIN olympic.tb_register

           ON tb_register.athlete_id = tb_athlete.athlete_id

      INNER JOIN olympic.tb_discipline

           ON tb_discipline.discipline_id = tb_register.discipline_id

      ORDER BY  tb_register.register_ts;
      
      RETURN NEXT data_sponsor;
 END;
 $LANGUAGE plpgsql;
 

 SELECT * FROM fn_get_info_by_sponsor('2021-06-02 00:00:00','Reebok')
       
 

Я предполагаю, что я допустил ошибку в операторе DECLARE, но я не уверен, как это решить. Кто-нибудь может помочь?

(Я использовал несколько таблиц, поэтому я не добавляю здесь инструкции CREATE TABLE для упрощения)

Спасибо (:

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

1. 1) Это не имеет никакого отношения к MySQL so, я удалил тег 2) Функция нарушена несколькими способами, я бы предложил провести некоторое время здесь plpgsql . В частности, выберите into и верните запрос 43.6.1.2. ВЕРНИТЕ СЛЕДУЮЩИЙ и ВЕРНИТЕ ЗАПРОС.

2. Спасибо @AdrianKlaver, я обновил вопрос.

Ответ №1:

Здесь вы можете создать простую функцию sql вместо функции plpgsql. Просто проверьте список полей, предоставленных запросом, и которые должны соответствовать sponsor_data типу в правильном порядке полей.

 CREATE OR REPLACE FUNCTION fn_get_info_by_sponsor
       (register_date tb_register.register_ts%type, sponsor_name tb_sponsor.name%type)
RETURNS sponsor_data LANGUAGE sql AS $
      SELECT row(
                 tb_sponsor.email,
                 tb_finance.sponsor_name,
                 tb_athlete.name AS athlete_name,
                 tb_discipline.name AS discipline_name,
                 tb_register.round_number,
                 tb_register.register_measure, -- = mark of type CHARACTER(12) ?
                 tb_register.register_position,
                 tb_register.register_ts -- = register_date of type date ?
                ) :: sponsor_data 
      FROM  olympic.tb_sponsor
      INNER JOIN olympic.tb_finance
           ON (tb_finance.sponsor_name = tb_sponsor.name)
      INNER JOIN olympic.tb_athlete
           ON tb_athlete.athlete_id = tb_finance.athlete_id
      INNER JOIN olympic.tb_register
           ON tb_register.athlete_id = tb_athlete.athlete_id
      INNER JOIN olympic.tb_discipline
           ON tb_discipline.discipline_id = tb_register.discipline_id
      ORDER BY  tb_register.register_ts ;
$ 

 SELECT * FROM fn_get_info_by_sponsor('2021-06-02 00:00:00','Reebok')
 

Или вы можете создать функцию PL / pgSQL для выполнения того же :

 CREATE OR REPLACE FUNCTION fn_get_info_by_sponsor
       (register_date tb_register.register_ts%type, sponsor_name tb_sponsor.name%type)
RETURNS sponsor_data LANGUAGE plpgsql AS $
DECLARE
      sp_data sponsor_data ;
BEGIN
      SELECT row(
                 tb_sponsor.email,
                 tb_finance.sponsor_name,
                 tb_athlete.name AS athlete_name,
                 tb_discipline.name AS discipline_name,
                 tb_register.round_number,
                 tb_register.register_measure, -- = mark of type CHARACTER(12) ?
                 tb_register.register_position,
                 tb_register.register_ts -- = register_date of type date ?
                ) :: sponsor_data
       INTO sp_data
       FROM olympic.tb_sponsor
      INNER JOIN olympic.tb_finance
           ON (tb_finance.sponsor_name = tb_sponsor.name)
      INNER JOIN olympic.tb_athlete
           ON tb_athlete.athlete_id = tb_finance.athlete_id
      INNER JOIN olympic.tb_register
           ON tb_register.athlete_id = tb_athlete.athlete_id
      INNER JOIN olympic.tb_discipline
           ON tb_discipline.discipline_id = tb_register.discipline_id
      ORDER BY  tb_register.register_ts ;

      RETURN sp_data ;
END ;  
$ 

 SELECT * FROM fn_get_info_by_sponsor('2021-06-02 00:00:00','Reebok')
 

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

1. Спасибо @Eduard, это действительно полезно. Но я хотел бы понять разницу между slq и plpgsql и иметь возможность использовать оба. Я обновил свой вопрос.

2. SQL — это язык для взаимодействия с любыми системами управления реляционными базами данных, такими как PostgreSQL, MySQL, Oracle… Вы можете либо создать функции языка запросов (SQL) , либо процедурный язык, такой как функции PL / pgSQL . PL / pgSQL может делать больше, чем SQL см. Руководство .

3. Ответ обновлен с помощью эквивалентной функции PL / pgSQL.

4. @Eduard спасибо за всю помощь. Проблема решена. Теперь мне просто нужно погрузиться в руководство, которое вы рекомендовали. Спасибо (:

5. @KlauRau — Функции SQL — это макросы /- в экосистемах PostgreSQL — вы можете написать «параметризованные представления» — функциональность такая же, как и представления, но допускает параметризацию. Функции PL / pgSQL позволяют использовать полную функциональность хранимых процедур — процедурный язык встроенный SQL. Преимущества функций SQL встраиваются. Функции PL / pgSQL могут использовать полную функциональность, но для планировщика это черный ящик. Функции SQL могут быть встроены во внешний запрос и оптимизированы вместе. Это невозможно для функций PL / pgSQL.