перебирать идентификаторы и использовать в запросе postgres функцию - PullRequest
1 голос
/ 26 мая 2020

Для контекста

Я хочу создать функцию в postgres, которая заполняет таблицу соединений pokemon_trainers со следующими столбцами

  • id
  • trainer_id
  • pokemon_id

trainer_id - ссылка на строку в таблице trainers

и pokemon_id - ссылка к строке в таблице pokemons

У каждого трейнера должно быть 6 покемонов. Итак, если есть 10000 трейнеров, в таблице pokemon_trainers должно быть 60000 строк. Я хотел бы решить эту проблему в postgres, не зависимо от приложения для обработки logi c.

Актуальная проблема

Я предполагаю, что он должен проходить через каждую trainer строку и выполнить 6 вставок для каждого trainer.

, каждая вставка пытается выбрать случайный pokemons.id для использования, что, похоже, работает нормально. Однако у меня возникли проблемы с определением trainer.id и использованием его внутри запроса INSERT внутри вложенного l oop.

CREATE OR REPLACE FUNCTION populate_trainer_pokemons() 
  RETURNS VOID 
AS
$$
DECLARE 
   trainer_pokemon trainer_pokemons%rowtype;
BEGIN
    FOR trainer_pokemon in SELECT id FROM trainer_pokemons LOOP
  FOR i IN 0..6 LOOP
        INSERT INTO trainer_pokemons(trainer_pokemon.id, pokemon_id)
VALUES(trainer_id, (SELECT
   FLOOR(RANDOM() *
   (
      (SELECT
             min(id)  
          FROM
             pokemons) -
      ((SELECT
            max(id)  
         FROM
            pokemons) + 1
   )) +1
) + 
(SELECT
   max(id)  
FROM
   pokemons)));
   END LOOP;
    END LOOP;
END;
$$ 
LANGUAGE plpgsql;
SELECT populate_trainer_pokemons();

дает следующую ошибку:

ОШИБКА: столбец «trainer_pokemon» отношения «trainer_pokemons» не существует. СТРОКА 1: ВСТАВИТЬ trainer_pokemons (trainer_pokemon.id, pokemon_id)

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

Как мне заставить эту функцию работать?

1 Ответ

1 голос
/ 26 мая 2020

Нет необходимости в функции или дорогих циклах. Это можно сделать с помощью одного оператора:

INSERT INTO trainer_pokemons(trainer_id, pokemon_id)
select tr.id, x.id
from trainers tr
  cross join lateral (
    select id
    from pokemons
    order by random() 
    limit 6
  ) x
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...