Reputation: 25566
Table 1:
id name desc
-----------------------
1 a abc
2 b def
3 c adf
Table 2:
id name desc
-----------------------
1 x 123
2 y 345
In oracle SQL, how do I run an sql update query that can update Table 1 with Table 2's name
and desc
using the same id
? So the end result I would get is
Table 1:
id name desc
-----------------------
1 x 123
2 y 345
3 c adf
Question is taken from update one table with data from another, but specifically for oracle SQL.
Upvotes: 334
Views: 1393013
Reputation: 9765
Oracle Database 23ai has added direct joins for update
and delete
:
create table t1 (
c1 int, c2 int
);
create table t2 (
c1 int, c2 int
);
insert into t1 values ( 1, 1 ), ( 2, 2 );
insert into t2 values ( 1, 42 );
select * from t1;
C1 C2
---------- ----------
1 1
2 2
update t1
set t1.c2 = t2.c2
from t2
where t1.c1 = t2.c1;
select * from t1;
C1 C2
---------- ----------
1 42
2 2
delete t1
from t2
where t1.c1 = t2.c1;
select * from t1;
C1 C2
---------- ----------
2 2
Upvotes: 4
Reputation: 111
Here seems to be an even better answer with 'in' clause that allows for multiple keys for the join:
update fp_active set STATE='E',
LAST_DATE_MAJ = sysdate where (client,code) in (select (client,code) from fp_detail
where valid = 1) ...
The full example is here: http://forums.devshed.com/oracle-development-96/how-to-update-from-two-tables-195893.html - from web archive since link was dead.
The beef is in having the columns that you want to use as the key in parentheses in the where clause before 'in' and have the select statement with the same column names in parentheses. where (column1,column2) in ( select (column1,column2) from table where "the set I want" );
Upvotes: 10
Reputation: 8485
Try this:
MERGE INTO table1 t1
USING
(
-- For more complicated queries you can use WITH clause here
SELECT * FROM table2
)t2
ON(t1.id = t2.id)
WHEN MATCHED THEN UPDATE SET
t1.name = t2.name,
t1.desc = t2.desc;
Upvotes: 263
Reputation: 27
BEGIN
For i in (select id, name, desc from table2)
LOOP
Update table1 set name = i.name, desc = i.desc where id = i.id and (name is null or desc is null);
END LOOP;
END;
Upvotes: -2
Reputation: 265
Update table set column = (select...)
never worked for me since set only expects 1 value - SQL Error: ORA-01427: single-row subquery returns more than one row.
here's the solution:
BEGIN
For i in (select id, name, desc from table1)
LOOP
Update table2 set name = i.name, desc = i.desc where id = i.id;
END LOOP;
END;
That's how exactly you run it on SQLDeveloper worksheet. They say it's slow but that's the only solution that worked for me on this case.
Upvotes: 15
Reputation: 571
If your table t1 and it's backup t2 have many columns, here's a compact way to do it.
In addition, my related problem was that only some of the columns were modified and many rows had no edits to these columns, so I wanted to leave those alone - basically restore a subset of columns from a backup of the entire table. If you want to just restore all rows, skip the where clause.
Of course the simpler way would be to delete and insert as select, but in my case I needed a solution with just updates.
The trick is that when you do select * from a pair of tables with duplicate column names, the 2nd one will get named _1. So here's what I came up with:
update (
select * from t1 join t2 on t2.id = t1.id
where id in (
select id from (
select id, col1, col2, ... from t2
minus select id, col1, col2, ... from t1
)
)
) set col1=col1_1, col2=col2_1, ...
Upvotes: -2
Reputation: 231651
This is called a correlated update
UPDATE table1 t1
SET (name, desc) = (SELECT t2.name, t2.desc
FROM table2 t2
WHERE t1.id = t2.id)
WHERE EXISTS (
SELECT 1
FROM table2 t2
WHERE t1.id = t2.id )
Assuming the join results in a key-preserved view, you could also
UPDATE (SELECT t1.id,
t1.name name1,
t1.desc desc1,
t2.name name2,
t2.desc desc2
FROM table1 t1,
table2 t2
WHERE t1.id = t2.id)
SET name1 = name2,
desc1 = desc2
Upvotes: 646
Reputation: 70369
try
UPDATE Table1 T1 SET
T1.name = (SELECT T2.name FROM Table2 T2 WHERE T2.id = T1.id),
T1.desc = (SELECT T2.desc FROM Table2 T2 WHERE T2.id = T1.id)
WHERE T1.id IN (SELECT T2.id FROM Table2 T2 WHERE T2.id = T1.id);
Upvotes: 27