RETURNING in INSERT INTO statement with a SELECT statement - postgresql

I am inserting data into a table and want to return the inserted data. The inserted data contains foreign keys. I would like to get the whole data with the joins of the foreign keys.
I have tried putting a SELECT in RETURNING without luck. Is this even possible or do I just have to do another query after inserting the data?
Insert statement:
INSERT INTO someTable (col1, col2, col3, foreign_id)
VALUES ('value1', 'value2', 'value3', 1);
So in this case, could I have a RETURNING that basically would give me:
SELECT someTable.*, foreignTable.*
FROM someTable
JOIN foreignTable ON someTable.foreign_id = foreignTable.id;

demo:db<>fiddle
You can use a CTE for this:
WITH inserting AS (
INSERT INTO...
RETURNING <new data>
)
SELECT i.*, ft.*
FROM inserting i JOIN foreign_table ft ...
In this case the INSERT statement will be executed. The SELECT statement will be executed after that. This can reference the inserted data.

You can use a CTE for that:
with new_row as (
INSERT INTO some_table (col1, col2, col3, foreign_id)
VALUES ('value1', 'value2', 'value3', 1)
returning *
)
SELECT new_row.*, ft.*
FROM new_row
JOIN foreign_table ft ON new_row.foreign_id = ft.id;

Related

Using cte with update in db2

I have set of queries which are getting repeated in update query for db2
I need to get rid of these getting repeated
So what best I can do. Cte is not working in update query in db2.
Not able to find solution. For select query cte is working but not for update
You may use so called "SELECT from data-change-table-reference" Db2 functionality using CTE.
CREATE TABLE MYTAB (ID INT, DATA INT);
INSERT INTO MYTAB (ID, DATA) VALUES (1, NULL);
WITH
UPD (ID, DATA) AS (VALUES (1, 1), (2, 2))
SELECT COUNT (1)
FROM NEW TABLE
(
UPDATE MYTAB T
SET DATA = U.DATA
FROM UPD U
WHERE T.ID = U.ID
);
SELECT * FROM MYTAB;
ID
DATA
1
1
fiddle

INSERT output of a subquery along with an autoincrement in postgres

I am trying to store the output of a WITH statement in an INSERT statement in postgres along with an autoincrement id.
Below is the query:
INSERT
INTO
table
(row_id,(
SELECT
*
FROM
final_dataset
));
However, I am getting a syntax error near "SELECT". I am unabe to figure out the solution to this.
Are you looking for this?
insert into the_table (col1, col2, col3)
select nextval('the_table_id_seq'), x1, x2
from final_dataset;
If col1 is a serial or identitycolumn, I would remove it completely:
insert into the_table (col2, col3)
select x1, x2
from final_dataset;

Copy rows into same table, but change value of one field

I have a list of values:
(56957,85697,56325,45698,21367,56397,14758,39656)
and a 'template' row in a table.
I want to do this:
for value in valuelist:
{
insert into table1 (field1, field2, field3, field4)
select value1, value2, value3, (value)
from table1
where ID = (ID of template row)
}
I know how I would do this in code, like c# for instance, but I'm not sure how to 'loop' this while passing in a new value to the insert statement. (i know that code makes no sense, just trying to convey what I'm trying to accomplish.
There is no need to loop here, SQL is a set based language and you apply your operations to entire sets of data all at once as opposed to looping through row by row.
insert statements can come from either an explicit list of values or from the result of a regular select statement, for example:
insert into table1(col1, col2)
select col3
,col4
from table2;
There is nothing stopping you selecting your data from the same place you are inserting to, which will duplicate all your data:
insert into table1(col1, col2)
select col1
,col2
from table1;
If you want to edit one of these column values - say by incrementing the value currently held, you simply apply this logic to your select statement and make sure the resultant dataset matches your target table in number of columns and data types:
insert into table1(col1, col2)
select col1
,col2+1 as col2
from table1;
Optionally, if you only want to do this for a subset of those values, just add a standard where clause:
insert into table1(col1, col2)
select col1
,col2+1 as col2
from table1
where col1 = <your value>;
Now if this isn't enough for you to work it out by yourself, you can join your dataset to you values list to get a version of the data to be inserted for each value in that list. Because you want each row to join to each value, you can use a cross join:
declare #v table(value int);
insert into #v values(56957),(85697),(56325),(45698),(21367),(56397),(14758),(39656);
insert into table1(col1, col2, value)
select t.col1
,t.col2
,v.value
from table1 as t
cross join #v as v

T-SQL Delete Inserted Records

I know the title may seem strange but this is what I want to do:
I have table with many records.
I want to get some of this records and insert them in other table. Something like this:
INSERT INTO TableNew SELECT * FROM TableOld WHERE ...
The tricky part is that I want this rows that I have inserted to be deleted form the origin table as well.
Is there a easy way to do this, because the only think that I have managed to do is to use a temporary table for saving the selected records and then to put them in the second table and delete rows that match with them from the first table. It is a solution, but with so many records (over 3 millions and half) I am looking for some other idea...
In 2005+ use OUTPUT clause like this:
DELETE FROM TableOld
OUTPUT DELETED.* INTO TableNew
WHERE YourCondition
It will be performed in single transaction and either completed or roll back simultaneously
You can use the insert ... output clause to store the ID's of the copied rows in a temporary table. Then you can delete the rows from the original table based on the temporary table.
declare #Table1 table (id int, name varchar(50))
declare #Table2 table (id int, name varchar(50))
insert #Table1 (id,name)
select 1, 'Mitt'
union all select 2, 'Newt'
union all select 3, 'Rick'
union all select 4, 'Ron'
declare #copied table (id int)
insert #Table2
(id, name)
output inserted.id
into #copied
select id
, name
from #Table1
where name <> 'Mitt'
delete #Table1
where id in
(
select id
from #copied
)
select *
from #Table1
Working example at Data Explorer.
You should do some thing like this:
INSERT INTO "table1" ("column1", "column2", ...)
SELECT "column3", "column4", ...
FROM "table2"
WHERE ...
DELETE FROM "table1"
WHERE ...

postgres: Setting the value of an array with a subquery?

In postgres, can you set the value of an array in an INSERT to the result of a subquery? Like:
INSERT INTO mytable
VALUES( SELECT list_of_integers FROM someothertable WHERE somekey = somevalue);
Where that mytable just has as its one column a type of integer[] and that other column list_of_integers is also type integer[] ?
You want the unnest function. I think you'd use it like:
INSERT INTO mytable
SELECT set_of_integers
FROM unnest(
SELECT list_of_integers
FROM someothertable
WHERE somekey = somevalue
) t(set_of_integers)
But i don't have PostgreSQL to hand to try it out myself.
Yes:
INSERT INTO
mytable
(column1, column2, an_array_of_integers_column)
VALUES
(2, 'bbb', (SELECT list_of_integers FROM someothertable WHERE somekey = somevalue));