Insert a row into the table if it does not exist using SQL - sql

I want to insert a row into the table if it does not exist.
I want to check if the col1 , col2 combination exists in the table.If not I have to insert the data.I have written a query like below , but it is not working.Can some one please help me.
INSERT INTO TABLE1 (COL1 , COL2 , COL3, COL4)
VALUES ( 1234 , 4567 , 'test_name_int' , 'test_disp_name' )
WHERE NOT EXISTS ( SELECT * FROM TABLE1 WHERE COL1 = 1234 and COL2 = '4567');

MERGE INTO is another good option. You could perform update too, if required.
This checks whether col1,col2 of the source and destination match. If they do not,then it does insert. you could also use WHEN MATCHED THEN UPDATE when required to do so.
MERGE INTO TABLE1 d
USING (SELECT 1235 COL1,
4568 COL2,
'test_name_int' COL3,
'test_disp_name' COL4
FROM DUAL) s
ON (d.COL1 = s.col1 AND d.COL2 = s.COL2)
WHEN NOT MATCHED
THEN
INSERT (COL1,
COl2,
COl3,
COl4)
VALUES (s.COl1,
s.COL2,
s.COL3,
s.COL4);

Maybe something like that:
Insert Into TABLE1
Select 1234 , 4567 , 'test_name_int' , 'test_disp_name'
From Dual
WHERE NOT EXISTS ( SELECT * FROM TABLE1 WHERE COL1 = 1234 and COL2 ='4567')

Related

How to use a variable as a select statement and then sum multiple values in a variable?

I have multiple rows with the following columns:
col1
col2
col3
col4
I want to say if rows where col3 equals col2 of other rows where col1 equals 'a111', then sum col4 of the rows where col3 equals col2 of other rows where col1 equals 'a111', and then rename the sum column to "Total".
Example table with the four columns and four rows:
col1 col2 col3 col4
---- ---- ---- ----
a222 a333 4444
a111 a333
a555 a444 1111
a111 a444
I've tried the following but it does not work.
Declare
var1 = Select col2 from table1 where col1='a111';
var2 = Select col3 from table1 where col3=var1;
var3 = Select col4 from table1 where col3=var1;
Begin
If var2=var1
Then Select SUM(var3) As "Total";
End
Expected result is:
Total
5555
I do not have the strongest of knowledge in programming overall or Oracle. Please ask any questions and I will do my best to answer.
Your logic is convoluted and hard to follow without an example of the data you have and an example of the data you want.. but translating your pseudocode into sql gives:
Declare
var1 = Select col2 from table1 where col1='[table2.col2 value]';
Called "find" in my query
var2 = Select col3 from table1 where col3=var1;
var3 = Select col4 from table1 where col3=var1;
Achieved by joining the table back to the "find"
Begin
If var2=var1
Then Select SUM(var3) As "Total";
End
Achieved with a sum of var3 on only rows where var1=var2, in "ifpart"
SELECT SUM(var3) FROM
(
SELECT alsot1.col3 as var2, alsot1.col4 as var3
FROM
table1 alsot1
INNER JOIN
(
SELECT t1.col2 as var1
FROM table1 t1 INNER JOIN table2 t2 ON t1.col1 = t2.col2
) find
ON find.var1 = alsot1.col3
) ifpart
WHERE
var1 = var2
This could be simplified, but I present it like this because it matches your understanding of the problem. The query optimizer will rewrite it anyway when the time comes to run it so it only pays to start messing with how it's done if performance is poor
By the way, you clearly said that two tables join via a common named col2 but you then in your pseudocode said the tables join on col1=col2. I followed your pseudocode
This sounds like something that hierarchical queries could handle. E.g. something like:
WITH your_table AS (SELECT NULL col1, 'a222' col2, 'a333' col3, 4444 col4 FROM dual UNION ALL
SELECT 'a111' col1, 'a333' col2, NULL col3, NULL col4 FROM dual UNION ALL
SELECT NULL col1, 'a555' col2, 'a444' col3, 1111 col4 FROM dual UNION ALL
SELECT 'a111' col1, 'a444' col2, NULL col3, NULL col4 FROM dual UNION ALL
SELECT 'a666' col1, 'a888' col2, NULL col3, NULL col4 FROM dual UNION ALL
SELECT NULL col1, 'a777' col2, 'a888' col3, 7777 col4 FROM dual)
SELECT col1,
SUM(col4) col4_total
FROM (SELECT connect_by_root(col1) col1,
col4
FROM your_table
CONNECT BY col3 = PRIOR col2
START WITH col1 IS NOT NULL) -- start with col1 = 'a111')
GROUP BY col1;
COL1 COL4_TOTAL
---- ----------
a666 7777
a111 5555
Nevermind. I believe I've determined the answer myself. I over complicated what I wanted. Thank you anyway.
Answer:
Select Sum(col4) as "Total" from table1 where col3 in (Select col2 from table1 where col1='a111')

How to write insert query from slect result which return more then one row using max+1 syntax

I am trying to write a SQL like below in DB2.
insert into tableA (col1, col2, col3)
select max(col1) + 1, '-2', col3
from tableA
where col2 = -1
Here the aim is copy all the record of tableA from -1 to -2 and here col1 is primary key and this should be increment by 1.
Now the problem is the select query will return more then one row like below
1001 -2 xyz
1001 -2 pqr
1001 -2 xdc
And it is not able to insert as the key is same.
Is there any way I can write the select sql so that it can return like below
1001 -2 xyz
1002 -2 pqr
1003 -2 xdc
and my insert will work, or is there any alternative way to the same with easiest way.
Note: The table do not have any trigger or some thing to auto increment the primary key.
Yes. Use row_number():
insert into tableA ( col1, col2, col3)
select max(col1) + row_number() over (order by col3), '-2', col3
from tableA
where col2 = -1
group by col3;
If you don't have a group by, then do:
insert into tableA ( col1, col2, col3)
select maxcol1 + row_number() over (order by col3), '-2', col3
from (select a.*, max(col1) over () as maxcol1
from tableA a
) a
where col2 = -1;
The right way to do this is to use a generated auto-incrementing value for col1. This code all has a problem if multiple threads are trying to do inserts at the same time.
Try this query !
insert into tableA (col1, col2, col3)
select (max(col1) + 1) as col1, '-2' as col2, col3
from tableA
where col2 = -1

Concatenate tables (UNION ALL) where one of the tables lacks one of the columns

I am trying to combine three tables in an SQLite database into one new combined table. The three tables have the same column names, but the third table is missing one of the columns. Here is how I am trying to do it:
CREATE TABLE cobmined
AS
SELECT col1, col2, col3
FROM
(
SELECT col1, col2, col3 from table1
UNION ALL
SELECT col1, col2, col3 from table2
UNION ALL
SELECT col1, col2 from table3
) s
;
This works when doing this only on the first two tables, when adding the third table I get the message:
SELECTs to the left and right of UNION do not have the same number of result columns
Is there a way to let SQL ignore the missing column and leave it with NULLs if needed?
Add a NULL value to the third table
CREATE TABLE cobmined
AS
SELECT col1, col2, col3
FROM
(
SELECT col1, col2, col3 from table1
UNION ALL
SELECT col1, col2, col3 from table2
UNION ALL
SELECT col1, col2, null from table3
) s
;
Also, no need for sub-query
CREATE TABLE cobmined
AS
SELECT col1, col2, col3 from table1
UNION ALL
SELECT col1, col2, col3 from table2
UNION ALL
SELECT col1, col2, null from table3
I want to note that you don't need the subquery:
CREATE TABLE combined AS
SELECT col1, col2, col3 from table1
UNION ALL
SELECT col1, col2, col3 from table2
UNION ALL
SELECT col1, col2, NULL from table3;
In addition, you may find that a view is more suitable for your purposes than an actual table.

Oracle: Insert into select... in the

What is the advantage of inserting into a select of a table over simply inserting into the table?
eg
insert into
( select COL1
, COL2
from Table1
where 1=2 <= this and above is the focus of the question.
) select COL3, COL4 from Table2 ;
It seems to do the same thing as:
insert into Table1
( COL1, COL2 )
select COL3, COL4 from Table2 ;
This is the first time I've seen this; our Sr Dev says there is some advantage but he can't remember what it is.
It may make sense in a way if one was inserting a "select *..." from a table with lots of columns, and we want to be lazy, but... we're not. We're enumerating each column in the table.
Database is Oracle 11gR2, but this query was written probably in 10g or before.
we want to be lazy
No, we use insert into table(col1, col2) select col2, col2 from ... when there is a lot of records (for example 1M) and we don't want to create a the values section for each. Let's imagine how much time it takes if you write
insert into table (col1, col2)
values (select col1, col2 from (select col1, col2, rownum rn from ...) where rn = 1);
insert into table (col1, col2)
values (select col1, col2 from (select col1, col2, rownum rn from ...) where rn = 2);
...
insert into table (col1, col2)
values (select col1, col2 from (select col1, col2, rownum rn from ...) where rn = 1000000);
insert select is faster way for copying data from one table(several tables) to an another table.
In a nutshell. It's a lot easier. Especially when you have a massive query that you dont wanna rebuild,or if you have a crapton of objects, or values you are inserting.
Without WITH CHECK OPTION specified, I don't know of any purpose for this syntax. If you specify WITH CHECK OPTION, you can effectively implement an ad-hoc check constraint within your insert statement.
insert into
( select COL1
, COL2
from Table1
where 1=2 WITH CHECK OPTION
) select COL3, COL4 from Table2 ;
The above will never insert a record, because 1 will never equal 2.
The statement below will insert a record as long as COL3 is less than 100, otherwise an exception is raised.
insert into
( select COL1
, COL2
from Table1
where COL1 < 100 WITH CHECK OPTION
) select COL3, COL4 from Table2 ;

How do I build a "if-else" SQL query in an INSERT?

I'm trying to copy columns from one SQLite table to another but replacing a boolean (0 or 1) with an enumeration (0 to 9). A given item could be in the table twice - once with each boolean setting. I want to copy the record with a true boolean preferentially, and if one doesn't exist then I want to copy the record with a false boolean.
Is there a way to do that in a single query?
I've included my current approach below, but that requires multiple queries to be run over the same set of tables so would be less efficient than just one query.
// Table schemas
Table1(Col1 text, Col2 text, Col3_bool int, Col4 int, Primary Key(Col1, Col2, Col3))
Table2(Col1 text, Col2 text, Col3_enum int, Col4 int, Primary Key(Col1, Col2, Col3))
// Pseudo code
for (int i = 0; i < 10; ++i)
{
insert into Table2 select Col1, Col2, i, Col4 from Table1 where Col3_bool = 0;
insert or replace into Table2 select Col1, Col2, i, Col4 from Table1 where Col3_bool = 1;
}
As long as you use a single transaction for all queries, it is unlikely that any performance difference is noticeable.
For each Col1/Col2 combination, you want the maximum Col3 value:
SELECT Col1, Col2, MAX(Col3_bool)
FROM Table1
GROUP BY Col1, Col2
You can then use these values to get the desired rows:
SELECT Table1.Col1,
Table1.Col2,
Table1.Col3_bool,
Table1.Col4
FROM Table1
JOIN (SELECT Col1,
Col2,
MAX(Col3_bool) AS Col3_bool
FROM Table1
GROUP BY Col1,
Col2
) USING (Col1, Col2, Col3_bool)
To get ten rows for each of these rows, do a cross join with another table with ten values:
INSERT INTO Table2
SELECT Table1.Col1,
Table1.Col2,
enums.i,
Table1.Col4
FROM Table1
JOIN (SELECT Col1,
Col2,
MAX(Col3_bool) AS Col3_bool
FROM Table1
GROUP BY Col1,
Col2
) USING (Col1, Col2, Col3_bool)
JOIN (SELECT 0 AS i UNION ALL
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6 UNION ALL
SELECT 7 UNION ALL
SELECT 8 UNION ALL
SELECT 9) AS enums