Verwenden Sie datenmodifizierende CTEs :
WITH ins1 AS (
INSERT INTO sample(firstname, lastname)
VALUES ('fai55', 'shaggk')
RETURNING id AS sample_id
)
, ins2 AS (
INSERT INTO sample1 (sample_id, adddetails)
SELECT sample_id, 'ss' FROM ins1
RETURNING user_id
)
INSERT INTO sample2 (user_id, value)
SELECT user_id, 'ss2' FROM ins2;
Jeder INSERT
hängt von dem vorhergehenden ab. SELECT
anstatt VALUES
sicherzustellen, dass nichts in Nebentabellen eingefügt wird, wenn keine Zeile von einer vorherigen zurückgegeben wird INSERT
. (Seit Postgres 9.5+ können Sie eine hinzufügen ON CONFLICT
.) Auf
diese Weise ist es auch etwas kürzer und schneller.
In der Regel ist es bequemer , vollständige Datenzeilen an einem Ort bereitzustellen :
WITH data(firstname, lastname, adddetails, value) AS (
VALUES
('fai55', 'shaggk', 'ss', 'ss2')
, ('fai56', 'XXaggk', 'xx', 'xx2')
)
, ins1 AS (
INSERT INTO sample (firstname, lastname)
SELECT firstname, lastname
FROM data
RETURNING firstname, lastname, id AS sample_id
)
, ins2 AS (
INSERT INTO sample1 (sample_id, adddetails)
SELECT ins1.sample_id, d.adddetails
FROM data d
JOIN ins1 USING (firstname, lastname)
RETURNING sample_id, user_id
)
INSERT INTO sample2 (user_id, value)
SELECT ins2.user_id, d.value
FROM data d
JOIN ins1 USING (firstname, lastname)
JOIN ins2 USING (sample_id);
db <> hier fummeln
Möglicherweise benötigen Sie explizite Typumwandlungen in einem eigenständigen VALUES
Ausdruck - im Gegensatz zu einem VALUES
Ausdruck, der an einen Ort angehängt ist, an INSERT
dem Datentypen aus der Zieltabelle abgeleitet werden. Sehen:
Wenn mehrere Zeilen mit identischen kommen können (firstname, lastname)
sein können, müssen Sie möglicherweise zuerst Duplikate falten INSERT
:
...
INSERT INTO sample (firstname, lastname)
SELECT DISTINCT firstname, lastname FROM data
...
Sie können anstelle des CTE eine (temporäre) Tabelle als Datenquelle verwenden data
.
Es wäre wahrscheinlich sinnvoll, dies mit einer EINZIGARTIGEN Einschränkung zu kombinieren (firstname, lastname)
in der Tabelle und einer ON CONFLICT
Klausel in der Abfrage .
Verbunden:
INSERT INTO sample1 (user_id, adddetails)
nicht sein(sample_id, addetails)
?Etwas wie das
with first_insert as ( insert into sample(firstname,lastname) values('fai55','shaggk') RETURNING id ), second_insert as ( insert into sample1( id ,adddetails) values ( (select id from first_insert), 'ss') RETURNING user_id ) insert into sample2 ( id ,adddetails) values ( (select user_id from first_insert), 'ss');
Da die generierte ID aus der Einfügung in
sample2
nicht benötigt wird, habe ich diereturning
Klausel aus der letzten Einfügung entfernt.quelle
Normalerweise verwenden Sie eine Transaktion, um das Schreiben komplizierter Abfragen zu vermeiden.
http://www.postgresql.org/docs/current/static/sql-begin.html
http://dev.mysql.com/doc/refman/5.7/en/commit.html
Sie können auch einen CTE verwenden, vorausgesetzt, Ihr Postgres-Tag ist korrekt. Zum Beispiel:
with sample_ids as ( insert into sample(firstname, lastname) values('fai55','shaggk') RETURNING id ), sample1_ids as ( insert into sample1(id, adddetails) select id,'ss' from sample_ids RETURNING id, user_id ) insert into sample2(id, user_id, value) select id, user_id, 'val' from sample1_ids RETURNING id, user_id;
quelle
Sie können einen After-Insert-Trigger für die Sample-Tabelle erstellen, um ihn in die beiden anderen Tabellen einzufügen.
Das einzige Problem, das ich dabei sehe, ist, dass Sie keine Möglichkeit haben, Adddetails einzufügen. Es wird immer leer sein oder in diesem Fall ss. Es gibt keine Möglichkeit, eine Spalte in eine Probe einzufügen, die nicht tatsächlich in der Probentabelle enthalten ist, sodass Sie sie nicht zusammen mit der angeborenen Einfügung senden können.
Eine andere Möglichkeit wäre, eine gespeicherte Prozedur zum Ausführen Ihrer Einfügungen zu erstellen.
Sie haben die Frage mysql und postgressql gestellt, über welche Datenbank sprechen wir hier?
quelle