2017-01-11 5 views
2

У меня проблема с вложением данных в таблицы, связанные внешним ключом. В некоторых местах я читал, что есть команда «с», которая помогает в этих ситуациях, но я не совсем понимаю, как она используется.PostgreSQL - одновременно вставлять данные в несколько таблиц

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

CREATE TABLE participante 
    (
     id serial NOT NULL, 
     nome character varying(56) NOT NULL, 
     CONSTRAINT participante_pkey PRIMARY KEY (id), 
    ); 

    CREATE TABLE venda 
    (
     id serial NOT NULL, 
     inicio date NOT NULL, 
     CONSTRAINT venda_pkey PRIMARY KEY (id) 
    ); 

    CREATE TABLE item 
    (
     id serial NOT NULL, 
     nome character varying(256) NOT NULL, 
     CONSTRAINT item_pkey PRIMARY KEY (id) 
    ); 


    CREATE TABLE lances_vendas 
    (
     id serial NOT NULL, 
     venda_id integer NOT NULL, 
     item_id integer NOT NULL, 
     participante_id integer NOT NULL, 
     valor numeric NOT NULL, 
     CONSTRAINT lance_vendas_pkey PRIMARY KEY (id), 
     CONSTRAINT lances_vendas_venda_id_fkey FOREIGN KEY (venda_id) 
     REFERENCES venda (id), 
     CONSTRAINT lances_vendas_item_id_fkey FOREIGN KEY (item_id) 
     REFERENCES item (id), 
     CONSTRAINT lances_vendas_participante_id_fkey FOREIGN KEY (participante_id) 
     REFERENCES participante (id) 
    ); 

ответ

4
WITH par_key AS 
     (INSERT INTO participante (nome) VALUES ('Laurenz') RETURNING id), 
    ven_key AS 
     (INSERT INTO venda (inicio) VALUES (current_date) RETURNING id), 
    item_key AS 
     (INSERT INTO item (nome) VALUES ('thing') RETURNING id) 
INSERT INTO lances_vendas (venda_id, item_id, participante_id, valor) 
    SELECT ven_key.id, item_key.id, par_key.id, numeric '3.1415' 
    FROM par_key, ven_key, item_key; 
0

Я знаю, что вы запросили один запрос, но вы все равно можете рассмотреть возможность использования сделки:

BEGIN; 
INSERT INTO participante (nome) VALUES ('Laurenz'); 
INSERT INTO venda (inicio) VALUES (current_date); 
INSERT INTO item (nome) VALUES ('thing'); 
INSERT INTO lances_vendas (venda_id, item_id, participante_id, valer) 
VALUES (currval('venda_id_seq'), currval('item_id_seq'), currval('participante_id_seq'), 3.1415); 
COMMIT; 

сделка гарантирует, что любая новая строка в partante, venda и item оставляет значение currval ('X') неизменным.

+1

последовательности не являются транзакционными, поэтому небезопасно полагаться на транзакцию здесь. – fpietka

+0

Как это опасно? Побочный эффект nextval() сразу отображается за пределами транзакции, и именно поэтому он (предположительно, как вам кажется, не убежден) безопасен для использования его результата. –

+0

Следующее обсуждение может стать для вас более ясным: http://stackoverflow.com/questions/2095917/sequences-not-affected-by-transactions –

0

Вы можете создать функцию для выполнения этой задачи. Посмотрите на этом примере:

CREATE OR REPLACE FUNCTION import_test(p_title character varying, p_last_name character varying, p_first_name character varying, p_house_num integer, p_street character varying, p_zip_code character varying, p_city character varying, p_country character varying) 
RETURNS integer 
LANGUAGE plpgsql 
AS 
$body$ 
DECLARE 

    address_id uuid; 
    parent_id uuid; 
    ts timestamp; 

BEGIN 

    address_id := uuid_generate_v4(); 
    parent_id := uuid_generate_v4(); 
    ts := current_timestamp; 

    insert into address (id, number, street, zip_code, city, country, date_created) values (address_id, p_house_num, p_street, p_zip_code, p_city, p_country, ts); 
    insert into person (id, title, last_name, first_name, home_address, date_created) values (parent_id, p_title, p_last_name, p_first_name, address_id, ts); 

RETURN 0; 
END; 
$body$ 
VOLATILE 
COST 100; 

COMMIT; 

Обратите внимание, как генерируемый UUID для address (первой вставки) используются в person -record (второй вставке)

Usage:

SELECT import_test('MR', 'MUSTERMANN', 'Peter', '[email protected]', 54, 'rue du Soleil', '1234', 'Arlon', 'be'); 
SELECT import_test('MS', 'MUSTERMANN', 'Peter 2', '[email protected]', 55, 'rue de la Lune', '56789', 'Amnéville', 'fr'); 
Смежные вопросы