PostgreSQL: вставка кортежей в несколько таблиц с использованием представления и триггера - PullRequest
1 голос
/ 31 января 2020

Я пытаюсь создать систему заказов, которая способна вставить составной заказ, состоящий из нескольких позиций и сумм. Моя база данных выглядит следующим образом: у меня есть таблица order, содержащая автоинкременты id, item_id, amount и order_group_id. У меня также есть таблица order_group, содержащая автоинкремент id и столбец person_id. Идея состоит в том, что, когда человек заказывает, создается одна новая запись order_group, и ее id используется как fk в orders, который сделал человек.

Я предполагаю, что это Обычно это делается в коде приложения. Тем не менее, я использую postgrest для предоставления мне API, который предлагает создать настраиваемое представление для вставки составных записей по этому маршруту. Это описано здесь .

Это то, что я имею до сих пор:

CREATE FUNCTION kzc.new_order()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
    DECLARE
        group_id int;
    BEGIN
        INSERT INTO kzc.order_group (person) VALUES (new.person) RETURNING id AS group_id;
        INSERT INTO kzc."order" (item, amount, order_group) VALUES (new.item_id, new.amount, group_id);
        RETURN new;
    END;
$$;

CREATE TRIGGER new_order
INSTEAD OF INSERT ON kzc.new_order
FOR EACH ROW
EXECUTE FUNCTION kzc.new_order()

Однако, этот код создает новый ordergroup для каждого order, который находится в составной вставке. Как я могу сделать так, чтобы мой код делал только одну новую запись ordergroup и присваивал ее id всем заказам?

Заранее спасибо!

1 Ответ

1 голос
/ 31 января 2020

Я предлагаю добавить столбец order_group_id в представление new_order и создать для него последовательность. Затем создайте значение DEFAULT для столбца:

ALTER VIEW kzc.new_order
   ALTER order_group_id SET DEFAULT currval('order_group_id_seq');

Добавьте BEFORE INSERT триггер FOR EACH STATEMENT, который просто вызывает nextval для последовательности. Все вызовы currval получат одно и то же сгенерированное значение.

Тогда у вас есть этот номер в вашем триггере и вы можете использовать его в качестве первичного ключа для order_group.

Чтобы избежать добавления строка несколько раз, используйте

INSERT INTO kzc.order_group (id, person)
   VALUES (NEW.order_group_id, NEW.person)
   ON CONFLICT (id) DO NOTHING;
...