ORACLE : Update query using two table with has relation - sql

I need to update the column data based on matching record found in both Table.
I want to update the record of NAME column from TABLE2
Following are the tables
Table1
---------------
Id | Name | color
1 | abc | red
2 | def | green
3 | ghi | blue
Table2
---------------
Id | Name | color |fiedId
1 | abc | red | 1
2 | def | green | 1
3 | ghi | blue | 2
Here table1 ID column is the Foreign Key in table2 as fieldId.
So, I want to update all the record which fall under this condition
table1.id = table2.fieldId

Yet another option, using MERGE:
merge into table2 t2
using (select id, name from table1) x
on (t2.fieldid = x.id)
when matched then update set
t2.name = x.name;
Or, for setting the name to 'xxx':
merge into table2 t2
using (select id from table1) x
on (t2.fiedid = x.id)
when matched then update set
t2.name = 'xxx';

Sounds like you just want an update like this:
update table2 t2
set t2.name =
( select t1.name
from table1 t1
where t1.id = t2.fieldid )
Regarding the followup question:
what if i want to set Name = "xxx" for all matching rows?
update table2 t2
set t2.name = 'xxx'
where t2.fieldid in
( select t1.id from table1 t1 )
or this can be written as:
update table2 t2
set t2.name = 'xxx'
where exists
( select null from table1 t1
where t1.id = t2.fieldid )

Related

Checking if a set of values exists in multiple tables

I'd like to know better ways of checking if a set of values is a subset of another.
For some reason, I can't make IN work so I use something like this approach:
-- check if `table1.id` is in other tables
SELECT (
-- check if all `table1.id` is in table2's `table1_id`
ARRAY(SELECT id FROM table1) <# ARRAY(SELECT table1_id FROM table2)
AND
-- check if all `table1.id` is in table3's `table1_id`
ARRAY(SELECT id FROM table1) <# ARRAY(SELECT table1_id FROM table3)
-- ...and so on
)
So for example, if I have these these two rows on table1:
+----+
| id |
+----+
| 1 |
| 2 |
+----+
And these two rows on table2:
+----+-----------+
| id | table1_id |
+----+-----------+
| 1 | 1 |
| 2 | 2 |
+----+-----------+
And this one row at table3:
+----+-----------+
| id | table1_id |
+----+-----------+
| 1 | 2 |
+----+-----------+
The result would be false because table3 does not contain both line_id of 1 and 2.
But, if table3 is like below:
+----+-----------+
| id | table1_id |
+----+-----------+
| 1 | 2 |
| 2 | 1 |
+----+-----------+
It would return true
Is my approach already good? If I use IN correctly, would it be faster? Are there some other ways that I am totally missing?
You can just use inner joins and count the results:
with table1_count as (
select count(*) as count
FROM table1
),
all_table_count as (
select count(*) as count
from (
select table1.id from table1
join table2 on table1.id = table2.table1_id
join table3 on table1.id = table3.table1_id
) sub
)
select table1_count.count = all_table_count.count as ids_everywhere
from all_table_count,table1_count
;
ids_everywhere
----------------
f
(1 row)
Joining will be much faster than array comparison.
Use exists
select t1.*
from Table1 t1
where exists (select 1 from table2 t2 where t2.table1_id = t1.id)
and exists (select 1 from table3 t3 where t3.table1_id = t1.id)
and exists (select 1 from table4 t4 where t4.table1_id = t1.id)
You can also use exists in a case statement
select t1.id,
case
when exists (select 1 from table2 t2 where t2.table1_id = t1.id)
and exists (select 1 from table3 t3 where t3.table1_id = t1.id)
and exists (select 1 from table4 t4 where t4.table1_id = t1.id)
then 1
else 0
end
from Table1 t1
Or list each separate (edit):
select t1.id,
case
when exists (select 1 from table2 t2 where t2.table1_id = t1.id)
then 1 else 0
end as in_tab2,
case
when exists (select 1 from table3 t3 where t3.table1_id = t1.id)
then 1 else 0
end as in_tab3,
case
when exists (select 1 from table4 t4 where t4.table1_id = t1.id)
then 1 else 0
end as in_tab4
from table1

SQL Join and Update query

So I want to update the action column to the value 'Insert' inside Table1, if the ids from Table1 and Table2 match but the UIDs dont.
Right now my query looks like
UPDATE Table1
SET Action = 'Insert'
FROM Table1
JOIN Table2 ON Table1.id = Table2.id
AND Table1.UID <> Table2.UID
This is setting the action to Insert even if the UIDs don't differ, can someone help me and explain why this is behaving this way?
My assumption is you have something like this:
Table1
id | UID | action
1 | 1 | bla
1 | 2 | bleck
1 | 3 | floop
Table2
id | UID | action
1 | 1 | bla
1 | 2 | bleck
1 | 4 | floop
And you hope to update the third row in Table1 because the UID isn't in Table2.
The problem is that the third row in Table2 matches all rows in Table1 on your condition: Table1.id = Table2.id AND Table1.UID <> Table2.UID
Which means that in this case, all rows in Table1 will be updated with Action = 'Insert'
I think you want to use NOT EXISTS():
UPDATE T1
SET Action = 'Insert'
FROM Table1 T1
WHERE NOT EXISTS (SELECT *
FROM Table2 T2
WHERE T1.id = T2.id
AND T1.UID = T2.UID)
Edit, more explanation on why the join fails:
This is a many to many join, meaning that the condition allows multiple rows from Table1 to match multiple rows from Table2
The easiest way to see this in action is to change your update to a select:
SELECT *
FROM Table1 T1
JOIN Table2 T2 on T1.id = T2.id
and T1.UID <> T2.UID
You may expect this to result in:
id | UID | action id | UID | action
1 | 3 | floop 1 | 4 | floop
But really it will result in:
id | UID | action id | UID | action
1 | 1 | bla 1 | 4 | floop
1 | 2 | bleck 1 | 4 | floop
1 | 3 | floop 1 | 4 | floop
This means that when you update you are hitting all the rows for id = 1 in Table1
If you put condition Table1.UID <> Table2.UID into WHERE clause, doesn't it solve your problem?
UPDATE Table1
SET Action = 'Insert'
FROM Table1
JOIN Table2 ON Table1.id = Table2.id
WHERE Table1.UID <> Table2.UID

update table from another table using like clause in oracle

i am new to stackoverflow. Am stuck with this problem for weeks but am unable to find similar examples to this (correct me if i am wrong). What i am trying to achieve is updating the values of one table from another table but using a look alike keywords eg. I have 2 tables
table1 (id, item) values:
id | item
-------------
10 | book
20 | copy
30 | pen
table2 (id,item) values:
id | item
-------------
null | the big book
null | the copy machine
null | penpal
Now I want to:
Update table2 A
Set id = Select id From table1 B
Where A.item Like B.item;
My desired outcome is:-
id | item
-------------
10 | the big book
20 | the copy machine
30 | penpal
How do it do it? Thank you all.
update table2 set id =
(select min(id) from table1
where table2.item like '%' || table1.item ||'%' );
Merge :
MERGE INTO Table2 tar
USING
(
SELECT MIN(T1.ID) AS ID, T2.item AS item
Table2 T2
LEFT JOIN
Table1 T1
ON (T2.item LIKE '%'||T1.item||'%')
GROUP BY T2.item
) src
ON (tar.item = src.item)
WHEN MATCHED THEN UPDATE
SET tar.id = src.id;
This solution may be faster.
update table2 t2
set id = ( select min(id) from table1 t1 where item like '%' || t1.item || '%')
where exists ( select 1 from table1 t1 where item like '%' || t1.item || '%');

Update multiple rows using select statements

Let's say I have these tables and values:
Table1
------------------------
ID | Value
------------------------
2 | asdf
4 | fdsa
5 | aaaa
Table2
------------------------
ID | Value
------------------------
2 | bbbb
4 | bbbb
5 | bbbb
I want to update all the values in Table2 using the values in Table1 with their respective ID's.
I know I can run this:
UPDATE Table2
SET Value = t1.Value
FROM Table2 t2
INNER JOIN Table1 t1 on t1.ID = t2.ID
But what can I do if Table1 and Table2 are actually select statements with criteria? How can I modify the SQL statement to take that into consideration?
This is how such update queries are generally done in Oracle. Oracle doesn't have an UPDATE FROM option:
UPDATE table2 t2
SET t2.value = ( SELECT t1.value FROM table1 t1
WHERE t1.ID = t2.ID )
WHERE EXISTS ( SELECT 1 FROM table1 t1
WHERE t1.ID = t2.ID );
The WHERE EXISTS clause will make sure that only the rows with a corresponding row in table1 are updated (otherwise every row in table2 will be updated; those without corresponding rows in table1 will be updated to NULL).

Removing intermediate table

Given the following tables:
Table1
| id | intermediate_id |
Itermediate
| id |
Table2
| id | intermediate_id | table1_id|
How do i update Table2 with Table1.ids?
I'm trying the following:
update Table2
set table1_id =
(select table1.id
from table1
where table1.intermediate_id = table2.intermediate_id);
which gives me "ERROR: more than one row returned by a subquery used as an expression"
update Table2
set table1_id = table1.id
from table1
where table1.intermediate_id = table2.intermediate_id