Nano Hash - криптовалюты, майнинг, программирование

Функция Postgres для заполнения набора записей и возвращаемого идентификатора

Я пытаюсь INSERT записать запись, вернуть идентификатор, а затем передать идентификатор другим таблицам и вставить дополнительные данные. Вставляемые данные имеют формат JSON.

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

Ошибка, которую я получаю, такова:

ERROR: INSERT has more target columns than expressions
SQL state: 42601
Context: PL/pgSQL function insert_to_tables(jsonb,jsonb,jsonb) line 3 at SQL statement

Вот как выглядят мои таблицы:

CREATE TABLE main_data(
  id SERIAL PRIMARY KEY,
  field_1 TEXT,
  some_time DATE
);

CREATE TABLE locale_data(
  locale_id SERIAL PRIMARY KEY,
  city TEXT,
  state TEXT,
  address TEXT,
  main_data_id INTEGER REFERENCES main_data(id)
);

CREATE TABLE demographic_data(
  demographic_id SERIAL PRIMARY KEY,
  age INT,
  ethnicity TEXT,
  main_data_id INTEGER REFERENCES main_data(id)
);

У меня есть такая функция для обработки ввода и анализа данных:

CREATE OR REPLACE FUNCTION insert_to_tables (
main_data_fields JSONB,
locale_data_fields JSONB,
demographic_data_fields JSONB,
OUT new_user_id INTEGER
)
RETURNS integer AS $$
BEGIN
   WITH ins AS (
      INSERT INTO main_data SELECT * FROM jsonb_populate_recordset(NULL::main_data, $1::jsonb)
      RETURNING id
      )

   INSERT INTO locale_data(city, state, address, main_data_id)
   SELECT i.id AS main_data_id, jsonb_populate_recordset(NULL::locale_data, $2::jsonb)
   FROM  ins i;
   INSERT INTO demographic_data(age, ethnicity)
   SELECT i.id AS main_data_id, jsonb_populate_recordset(NULL::demographic_data, $3::jsonb)
   FROM  ins i;
END;
$$ LANGUAGE plpgsql;

Чтобы вставить данные, я вызываю функцию следующим образом:

select insert_to_tables(
'{"field_1": "http://www.google.com", "some_time": "09-02-2019"}',
'[{"city": "a city", "address": "123 fake road", "state": "CA"}, {"city": "little city", "address": "456 noname road", "state": "WA"}]',
'[{"age": 45, "ethnicity": "Asian"}, {"age": "45", "ethnicity": "Egyptian"}]'
);

Моим ожидаемым результатом должна быть таблица main_data, заполненная 1 строкой, таблица locale_data, заполненная 2 строками, и таблица demographic_data, заполненная 2 строками.

Каждая из строк в таблице locale и demographic принадлежит и должна ссылаться на строку в таблице main_data следующим образом:

id  |         field1_1        | some_time  |
----+-------------------------+------------+
 1  |  http://www.google.com  |  09-02-2019


locale_id  |    city        |  state  |     address      | main_data_id
-----------+----------------+---------+------------------+---------+
 1         |     a city     |   CA    | 123 fake road    |   1
 2         |   little city  |   WA    | 456 noname road  |   1

locale_id  |    age      |    ethnicity   |  main_data_id
-----------+-------------+----------------+------------------+
 1         |     45      |   Asian        |    1
 2         |     45      |   Egyptian     |    1 

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


  • jsonb_populate_recordset вернуть набор записей. не строка 03.11.2017
  • Возможно, это сработает для вас stackoverflow.com/questions/27215216/ postgres 9.4+ 03.11.2017

Ответы:


1

Основная проблема — при использовании jsonb_populate_recordset() вы должны следить за тем, чтобы количество значений json точно совпадало с количеством столбцов таблицы. Вы не хотите заполнять id таблиц, поскольку они последовательные, поэтому вам нужно указать список столбцов и соответствующий список выбора. Кроме того, функция jsonb_populate_recordset() работает с json-массивами, поэтому первый аргумент должен быть массивом, как и два других.

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

CREATE OR REPLACE FUNCTION insert_to_tables (
    main_data_fields JSONB,
    locale_data_fields JSONB,
    demographic_data_fields JSONB
)
RETURNS integer AS $$
    WITH ins AS (
        INSERT INTO main_data (field_1, some_time)
        SELECT field_1, some_time
        FROM jsonb_populate_recordset(NULL::main_data, $1::jsonb)
        RETURNING id
    ),
    ins_locale AS (
        INSERT INTO locale_data (city, state, address, main_data_id)
        SELECT city, state, address, ins.id
        FROM ins, jsonb_populate_recordset(NULL::locale_data, $2::jsonb)
    ),
    ins_demographic AS (
        INSERT INTO demographic_data (age, ethnicity, main_data_id)
        SELECT age, ethnicity, ins.id
        FROM ins, jsonb_populate_recordset(NULL::demographic_data, $3::jsonb)
    )
    SELECT id
    FROM ins;
$$ LANGUAGE sql;

SELECT insert_to_tables (
    '[{"field_1": "http://www.google.com", "some_time": "09-02-2019"}]',
    '[{"city": "a city", "address": "123 fake road", "state": "CA"}, {"city": "little city", "address": "456 noname road", "state": "WA"}]',
    '[{"age": 45, "ethnicity": "Asian"}, {"age": "45", "ethnicity": "Egyptian"}]'
);

Полный пример см. здесь.

03.11.2017
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..