Saving results from RETURNING in separate variables - sql

Problem
Say I have the following insert statement:
insert into table_1 (...) values (...), (...), (...);
Assuming I know those 3 rows will be correctly inserted (no clause is violated), how can I fetch the id field of each inserted row into a separate variabile in order for me to use it in the rest of the .sql script?
What I tried
I've read about returning which would presumably translate into:
insert into table_1 (...) values (...), (...), (...) returning id;
I've also read about with (Common Table Expressions) which could "save" the result of returning into a table for later use in the following insert statements;
but it appears that I would then have to get the ids as select id from temp_table associating some kind of selector to distinguish between each 3 rows.
Question
Is there a way to get the ids of each inserted row to later use them, separately, in a different insert statement?

You could use three CTEs:
with i1 as (
insert into table_1 (...) values (...)returning id
),
i2 as (
insert into table_1 (...) values (...) returning id
),
i3 as (
insert into table_1 (...) values (...) returning id
)
insert . . .;
This doesn't put the values into three variables. It does put them in three separate CTEs so each can be referred to individually.

Related

Insert into multiple Tables from CTE´s with Conditions, invalid Identifier

I have a working query and now I want to insert most of it´s data into some tables.
My problem is that I don´t know how to insert into multiple tables at the same time, use it together with CTE´s and the Conditionals.
works:
with join1 as (...),
with join2 as (...),
with join3 as (..),
with relevantData as (use the joins),
select * from relevantData r;
This returns everything I want to have.
Now I want to move the relevantData, depending on some conditions, into different tables.
I have tried:
insert all
when r.column1 is not null then
insert into table1(Signature) values (r.column1,r.column5)
when r.column30 <> 'barney'
insert into table2(Signature) values (r.column8,r.column10,r.column11)
with join1 as (...),
with join2 as (...),
with join3 as (..),
with relevantData as ()
select * from relevantData r;
I have put the insert all as the first line but then the last r.column in my values is always false. ie: when I remove "insert into table2..." then the r.column5 will not be recognized, when I add it again the r.column11 will not be recognized.
However, if I remove this insert stuff again and only select for r.column5 it will be shown.
The error is: ORA-00904 Invalid Identifier
You write only one time with keyword when writing cte's and when you write insert all clause then you only write into keyword not insert into like you did. Syntax goes:
INSERT ALL
WHEN CONDITION_1 THEN
INTO YOUR_TABLE_1 (COLUMN_LIST) VALUES (VALUE_LIST)
WHEN CONDITION_2 THEN
INTO YOUR_TABL_2 (COLUMN_LIST) VALUES (VALUE_LIST)
...
WITH CTE_1 AS (
SELECT STATEMENT
),
CTE_2 AS(
SELECT STATEMENT
)...
SELECT STATEMENT

How to get a key from another table in a insert into... Values SQL statement?

I am not very experienced in SQL statements and I am trying to combine a couple of statements to have less traffic to the db.(and to make sure no other actions can happen inbetween)...
I have two tables:
Table: R_LOTS
a.o. 2 columns: PK_R_LOT and LOTCODE
Table: R_LOTTRACKING
Columns: FK_R_LOT,TIMESTAMP,FK_MAGLOCATIES
I use the statement:
INSERT INTO R_LOTTRACKING (FK_R_LOT,TIMESTAMP,FK_MAGLOCATIES) VALUES (?,CURRENT_TIMESTAMP,?).
On the questionmarks I can fill in the values to send.
However, as you can imagine, I do not have the FK_R_LOT but I have the LOTCODE (of R_LOT).. Of course I can get the FK_R_LOT with a seperate SELECT PK_R_LOT FROM R_LOT WHERE LOTCODE=?; but is there a way to combine these statements?
I have seen some examples but then all information seems to come from the R_LOT table but I could not find a combination of VALUES and SELECT.
Summary:
I know: LOTCODE and FK_MAGLOCATIES
How to combine the statements to insert the row:
INSERT INTO R_LOTTRACKING (FK_R_LOT,TIMESTAMP,FK_MAGLOCATIES) VALUES (?,CURRENT_TIMESTAMP,?)
SELECT PK_R_LOT FROM R_LOT WHERE LOTCODE=?
Use a subquery:
INSERT INTO R_LOTTRACKING ( FK_R_LOT, ... )
VALUES ( (SELECT PK_R_LOT FROM R_LOT WHERE LOTCODE = ?), ... );
or use an insert select:
INSERT INTO R_LOTTRACKING ( FK_R_LOT, ... )
SELECT PK_R_LOT, ... FROM R_LOT WHERE LOTCODE = ?;

Use inserted value as a parameter for other inserts

There is a db2 database with two tables. The first one, table1, has autoincrement column ID. It is the foreign key for the table2.
A am writing an HTML generator for SQL queries. So with some input parameters it generates a query or multiple queries. It is not connected to the database.
What I need is to get that autoincrement field and use it in next queries.
So basically, the scenario is:
insert into table1;
select autogenerated field ID;
insert into table2 using that ID;
insert into table2 using that ID;
...some more similar inserts...
insert into table2 using that ID;
And all that SQL query should be generated and then used as a single SQL script.
I was thinking about something like this:
SELECT ID FROM FINAL TABLE (INSERT INTO Table1 (t1column1, t1column2, etc.)
VALUES (t1value1, t1value2, etc.))
But I don't know, how I can write the result into a variable so I could use it in next queries like this:
INSERT INTO Table2 (foreignKeyCol, t2column1, t2column2, etc.)
VALUES ($ID, t2value1, t2value2, etc.)
I could just paste that select instead of $ID, but the second query can be used several times with the same $ID and different values.
EDIT: DB2 10.5 on Linux.
You can chain several inserts together using CTEs, like so:
WITH idcte (id) as (
SELECT ID FROM FINAL TABLE (
INSERT INTO Table1 (t1column1, t1column2, etc.)
VALUES (t1value1, t1value2, etc.)
)
),
ins1 (id) as (
SELECT foreignKeyCol FROM FINAL TABLE (
INSERT INTO Table2 (foreignKeyCol, t2column1, t2column2, etc.)
SELECT id, t2value1, t2value2, etc.
FROM idcte
)
),
-- more CTEs
SELECT foreignKeyCol FROM FINAL TABLE (
-- your last INSERT ... SELECT FROM
)
Essentially you will have to wrap each INSERT into a SELECT FROM FINAL TABLE for this to work.
Alternatively, you can use a global variable to keep the ID value:
CREATE VARIABLE myNewId INT;
SET myNewId = (SELECT ID FROM FINAL TABLE (
INSERT INTO Table1 (t1column1, t1column2, etc.)
VALUES (t1value1, t1value2, etc.)
));
INSERT INTO Table2 (foreignKeyCol, t2column1, t2column2, etc.)
VALUES (myNewId, t2value1, t2value2, etc.);
DROP VARIABLE myNewId;
This assumes a recent version of Db2 for LUW.

Multiple row insert or select if exists

CREATE TABLE object (
object_id serial,
object_attribute_1 integer,
object_attribute_2 VARCHAR(255)
)
-- primary key object_id
-- btree index on object_attribute_1, object_attribute_2
Here is what I currently have:
SELECT * FROM object
WHERE (object_attribute_1=100 AND object_attribute_2='Some String') OR
(object_attribute_1=200 AND object_attribute_2='Some other String') OR
(..another row..) OR
(..another row..)
When the query returns, I check for what is missing (thus, does not exist in the database).
Then I will make an multiple row insert:
INSERT INTO object (object_attribute_1, object_attribute_2)
VALUES (info, info), (info, info),(info, info)
Then I will select what I just inserted
SELECT ... WHERE (condition) OR (condition) OR ...
And at last, I will merge the two selects on the client side.
Is there a way that I can combine these 3 queries, into one single queries, where I will provide all the data, and INSERT if the records do not already exist and then do a SELECT in the end.
Your suspicion was well founded. Do it all in a single statement using a data-modifying CTE (Postgres 9.1+):
WITH list(object_attribute_1, object_attribute_2) AS (
VALUES
(100, 'Some String')
, (200, 'Some other String')
, .....
)
, ins AS (
INSERT INTO object (object_attribute_1, object_attribute_2)
SELECT l.*
FROM list l
LEFT JOIN object o1 USING (object_attribute_1, object_attribute_2)
WHERE o1.object_attribute_1 IS NULL
RETURNING *
)
SELECT * FROM ins -- newly inserted rows
UNION ALL -- append pre-existing rows
SELECT o.*
FROM list l
JOIN object o USING (object_attribute_1, object_attribute_2);
Note, there is a tiny time frame for a race condition. So this might break if many clients try it at the same time. If you are working under heavy concurrent load, consider this related answer, in particular the part on locking or serializable transaction isolation:
Postgresql batch insert or ignore

SQL Server - Contain Multiples Values

I need retrieve a value of columm with SELECT. But, I have multiple values ...
I don't know what the user go select in checkbox...
Ex:
Insert Into MyTable (dados) Values ('a1') I want the result = Angulo 1
Insert Into MyTable (dados) Values ('a2';'a3') I want the result = Angulo 2
Insert into MyTable (dados) Values ('a3'; a1) I want the result = Angulo 3; Angulo 1
Insert into MyTable (dados) Values ('a6'; 'a7'; 'a4') I want the result = Angulo 6; Angulo 7;Angulo4
I am Trying with SELECT CASE WHEN. But it still fails...
I suspect you are asking how to use the IN keyword in your SELECT statements? It is a little unclear what you are trying to do.
Try this:
SELECT *
FROM MyTable
WHERE dados IN ('a6','a7','a4')
Assuming you have a table named MyTable and a column named dados with 3 rows in that table for a6, a7 and a4, this will return all the matches (in this case, all three rows).
Good luck.
When you say:
insert into MyTable(dados)
Values ('a6', 'a7', 'a4')
You are saying "I have one column to put data into called dados." Then, you are providing three values. This will fail in any database (even apart from the fact that the semicolons should be commas).
Perhaps you want:
insert into MyTable(dados)
Values ('a6;a7;a4')
That is only one value, a string.
This suggests a denormalized database. You might want three different rows in a table, one for each value, connected together by some key.
here are some examples if you're using sql server 2008 and above:
if(OBJECT_ID('tempdb..#dados') is not null)
DROP TABLE #dados
select top 100 * INTO #dados FROM
(
values(1,2,3),
(4,5,6),
(7,8,9)
) t(a,b,c)
select * FROM #dados
INSERT INTO #dados (a,b,c)
values(11,22,33),
(44,55,66),
(77,88,99)
SELECT * FROM #dados
INSERT INTO #dados (a,b,c)
SELECT * FROM
(
values(111,222,333),
(444,555,666),
(777,888,999)
) t(a,b,c)
SELECT * FROM #dados
If you want to insert multiple rows (not columns) the syntax is
Insert Into
MyTable (dados)
Values
('a1'),
('a2')
Looks like you're trying to ask for two things.
How to insert multiple values would be done in the following way:
Insert Into MyTable (dados) Values ('a6'),('a7'),('a4')
If you want to return the actual values 'Angulo' + the number, you can use the following:
CREATE TABLE MyTable
(
Dados varchar(255)
)
Insert Into MyTable (dados) Values ('a12')
Insert Into MyTable (dados) Values ('a2'),('a3')
Insert Into MyTable (dados) Values ('a3'),('a1')
Insert Into MyTable (dados) Values ('a6'),('a7'),('a4')
SELECT 'Angulo'+ SUBSTRING(dados,PATINDEX('%[0-9]%',dados),LEN(dados))
FROM MyTable
It will find the first number (assuming it's always the first number you're after) and get the rest of them. It will then append it with the prefix 'Angulo' (e.g Angulo1, Angulo7, etc)
If these aren't what you're after. Please can you explain further what you need.