Save return values from INSERT...RETURNING into temp table (PostgreSQL) - sql

I have a table table1 with columns id,value1 and value2.
Also I have a query
INSERT INTO table1(value1,value2) SELECT value3,value4 FROM table2 RETURNING id
that returns set of ids.
I want to store return values (these ids) in some temp table. Something like that:
INSERT INTO TEMP temp1 INSERT INTO table1(value1,value2) SELECT value3,value4 FROM table2 RETURNING id
How can I do it?
DBMS is PostgreSQL

with inserted as (
INSERT INTO table1 (value1,value2)
SELECT value3,value4
FROM table2
RETURNING id
)
insert into temp
select id
from inserted;
This requires Postgres 9.2 or later.

Two options.
If you need it just for one follow-up query, a with statement (see the horse's answer) is the easiest.
If you need it for more than one follow-up query, the other option is to not use insert ... returning, but rather create table as:
CREATE TEMPORARY TABLE foo AS
SELECT value3,value4 FROM table2
Caveats: if necessary, create the indexes you need on the table -- and analyze it if you do.

Related

SELECT * FROM NEW TABLE equivalent in Postgres

In DB2 I can do a command that looks like this to retrieve information from the inserted row:
SELECT *
FROM NEW TABLE (
INSERT INTO phone_book
VALUES ( 'Peter Doe','555-2323' )
) AS t
How do I do that in Postgres?
There are way to retrieve a sequence, but I need to retrieve arbitrary columns.
My desire to merge a select with the insert is for performance reasons. This way I only need to execute one statement to insert values and select values from the insert. The values that are inserted come from a subselect rather than a values clause. I only need to insert 1 row.
That sample code was lifted from Wikipedia Insert Article
A plain INSERT ... RETURNING ... does the job and delivers best performance.
A CTE is not necessary.
INSERT INTO phone_book (name, number)
VALUES ( 'Peter Doe','555-2323' )
RETURNING * -- or just phonebook_id, if that's all you need
Aside: In most cases it's advisable to add a target list.
The Wikipedia page you quoted already has the same advice:
Using an INSERT statement with RETURNING clause for PostgreSQL (since
8.2). The returned list is identical to the result of a SELECT.
PostgreSQL supports this kind of behavior through a returning clause in a common table expression. You generally shouldn't assume that something like this will improve performance simply because you're executing one statement instead of two. Use EXPLAIN to measure performance.
create table test (
test_id serial primary key,
col1 integer
);
with inserted_rows as (
insert into test (c1) values (3)
returning *
)
select * from inserted_rows;
test_id col1
--
1 3
Docs

SQL Insert from other table with Same Schema

Table1 and Table2 have same schema, same columns and same types, and Table2 is empty while Table1 has some data
Insert into Table2 values(Select * from Table1)
how to transfer the data with sql statement? i think syntax is valid in oracle, but how to do with sql-server
You can leave out the values statement:
insert into table2
select * from table1
That said, you should really be in the habit of listing column names, both for the insert and select in this case. The columns could have the same name and type -- but be in different order.
You might possibly want to drop table 2 and then do a select * into table2 from table1. This way you are guaranteed to have the same structure. Because when somebody changes the structure of either table, but not the other, insert into will bomb.

SQL insert into using Union should add only distinct values

So I have this temp table that has structure like:
col1 col2 col3 col3
intID1 intID2 intID3 bitAdd
I am doing a union of the values of this temp table with a select query and storing
it into the same temp table.The thing is col3 is not part of the union query I will
need it later on to update the table.
So I am doing like so:
Insert into #temptable
(
intID1,
intID2,
intID3
)
select intID1,intID2,intID3
From
#temptable
UNION
select intID1,intID2,intID3
From
Table A
Issue is that I want only the rows that are not already existing in the temp table to be added.Doing it this way will add a duplicate of the already existing row(since union will return one row)How do I insert only those rows not existing in the current temp table in my union query?
Use MERGE:
MERGE INTO #temptable tmp
USING (select intID1,intID2,intID3 From Table A) t
ON (tmp.intID1 = t.intID1 and tmp.intID2 = t.intID2 and tmp.intID3 = t.intID3)
WHEN NOT MATCHED THEN
INSERT (intID1,intID2,intID3)
VALUES (t.intID1,t.intID2,t.intID3)
Nice and simple with EXCEPT
INSERT INTO #temptable (intID1, intID2, intID3)
SELECT intID1,intID2,intID3 FROM TableA
EXCEPT
SELECT intID1,intID2,intID3 FROM #temptable
I see where you are coming from. In most programming languages #temptable would be a variable (a relation variable or relvar for short) to which you would assign a value (a relation value) thus:
#temptable := #temptable UNION A
In the relational model, this would achieve the desired result because a relation has no duplicate rows by definition.
However, SQL is not truly relational and does not support assignment. Instead, you are required to add rows to a table using SQL DML INSERT statements (which is not so bad: the users of a truly relational database language, if we had one, would no doubt demand a similar shorthand for relational assignment!) but you are also required to do the test for duplicates yourself.
The answers from Daniel Hilgarth and Joachim Isaksson both look good. It's good practice to have two good, logically sound candidate answers then look for criteria (usually performance under typical load) to eliminate one (but retaining it commented out for future re-testing!)

Is it possible to copy some rows from one table to the other along with rowids?

If I type:
INSERT INTO table_b
SELECT rowid, somecolumn
FROM table_a
...the rowid column would copy into new table as ordinary column and this would most likely produce an error since columns wouldn't match.
But is there a way to copy exactly the same rowids from old table to new when I'm populating it fresh ?
I know it is possible to do it that way:
INSERT INTO table_b
(rowid, othercolumn)
VALUES (334, 'sometext')
...but that needs to be write row by row instead of one line sql command.
The first SQL you write is correct and will copy all information matching the columns.
You can also use a query like this:
INSERT INTO table2( rowId, rowValue)
SELECT rowId, rowValue FROM table1
Have you tried this:
INSERT INTO table_b (target_name, target_name2)
SELECT rowid, somecolumn
FROM table_a
Should work fine. But I've not done it on sqlite...

large insert in two tables. First table will feed second table with its generated Id

One question about how to t-sql program the following query:
Table 1
I insert 400.000 mobilephonenumbers in a table with two columns. The number to insert and identity id.
Table 2
The second table is called SendList. It is a list with 3columns, a identity id, a List id, and a phonenumberid.
Table 3
Is called ListInfo and contains PK list id. and info about the list.
My question is how should I using T-sql:
Insert large list with phonenumbers to table 1, insert the generated id from the insert of phonenum. in table1, to table 2. AND in a optimized way. It cant take long time, that is my problem.
Greatly appreciated if someone could guide me on this one.
Thanks
Sebastian
What version of SQL Server are you using? If you are using 2008 you can use the OUTPUT clause to insert multiple records and output all the identity records to a table variable. Then you can use this to insert to the child tables.
DECLARE #MyTableVar table(MyID int);
INSERT MyTabLe (field1, field2)
OUTPUT INSERTED.MyID
INTO #MyTableVar
select Field1, Field2 from MyOtherTable where field3 = 'test'
--Display the result set of the table variable.
Insert MyChildTable (myID,field1, field2)
Select MyID, test, getdate() from #MyTableVar
I've not tried this directly with a bulk insert, but you could always bulkinsert to a staging table and then use the processs, described above. Inserting groups of records is much much faster than one at a time.