I want to insert data into 3 tables with a single query.
My tables looks like below:
CREATE TABLE sample ( id bigserial PRIMARY KEY, lastname varchar(20), firstname varchar(20) ); CREATE TABLE sample1( user_id bigserial PRIMARY KEY, sample_id bigint REFERENCES sample, adddetails varchar(20) ); CREATE TABLE sample2( id bigserial PRIMARY KEY, user_id bigint REFERENCES sample1, value varchar(10) );
I will get a key in return for every insertion and I need to insert that key in the next table.
My query is:
insert into sample(firstname,lastname) values('fai55','shaggk') RETURNING id; insert into sample1(sample_id, adddetails) values($id,'ss') RETURNING user_id; insert into sample2(user_id, value) values($id,'ss') RETURNING id;
But if I run single queries they just return values to me and I cannot reuse them in the next query immediately.
How to achieve this?
PostgreSQL INSERT Multiple Rows First, specify the name of the table that you want to insert data after the INSERT INTO keywords. Second, list the required columns or all columns of the table in parentheses that follow the table name. Third, supply a comma-separated list of rows after the VALUES keyword.
2) Using PostgreSQL INNER JOIN to join three tables And each payment is processed by one and only one staff.
The T-SQL function OUTPUT, which was introduced in 2005, can be used to insert multiple values into multiple tables in a single statement. The output values of each row that was part of an INSERT, UPDATE or DELETE operation are returned by the OUTPUT clause.
Example 5: INSERT INTO SELECT statement with Join clause to get data from multiple tables. We can use a JOIN clause to get data from multiple tables. These tables are joined with conditions specified with the ON clause. Suppose we want to get data from multiple tables and insert into a table.
Use data-modifying CTEs:
WITH ins1 AS ( INSERT INTO sample(firstname, lastname) VALUES ('fai55', 'shaggk') -- ON CONFLICT DO NOTHING -- optional addition in Postgres 9.5+ 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;
Each INSERT
depends on the one before. SELECT
instead of VALUES
makes sure nothing is inserted in subsidiary tables if no row is returned from a previous INSERT
. (Since Postgres 9.5+ you might add an ON CONFLICT
.)
It's also a bit shorter and faster this way.
Typically, it's more convenient to provide complete data rows in one place:
WITH data(firstname, lastname, adddetails, value) AS ( VALUES -- provide data here ('fai55', 'shaggk', 'ss', 'ss2') -- see below , ('fai56', 'XXaggk', 'xx', 'xx2') -- works for multiple input rows -- more? ) , ins1 AS ( INSERT INTO sample (firstname, lastname) SELECT firstname, lastname -- DISTINCT? see below FROM data -- ON CONFLICT DO NOTHING -- UNIQUE constraint? see below 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<>fiddle here
You may need explicit type casts in a stand-alone VALUES
expression - as opposed to a VALUES
expression attached to an INSERT
where data types are derived from the target table. See:
If multiple rows can come with identical (firstname, lastname)
, you may need to fold duplicates for the first INSERT
:
... INSERT INTO sample (firstname, lastname) SELECT DISTINCT firstname, lastname FROM data ...
You could use a (temporary) table as data source instead of the CTE data
.
It would probably make sense to combine this with a UNIQUE constraint on (firstname, lastname)
in the table and an ON CONFLICT
clause in the query.
Related:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With