tags:

views:

35

answers:

6

I'm relatively new to Oracle, having working on MS SQL for most of my career. I'm used to doing stuff like:

update t
set Col1 = o.Col2
from MyTable t 
join OtherTable o on t.OtherID = o.ID

I tried this syntax in Oracle, and it doesn't accept it. Looked in Oracle docs and couldn't find an example of what I'm trying to do.

How do you do it?

A: 

Hello, you might be interested in MERGE statements.

Benoit
+2  A: 
update (select t.OtherID, t.Col1  , o.ID, o.Col2 from MyTable t 
join OtherTable o on t.OtherID = o.ID) a
set a.Col1 = a.Col2
guigui42
And what if the columns in `o` and `t` have the same names?
Shaul
yes, should never use * indeed.. i updated the query to name the fields specifically
guigui42
That works only if the subquery is "key-preserved" - see Dave Costa's answer.
Tony Andrews
The implication of this syntax is that you can update multiple tables simultaneously - is that true?
Shaul
As said in other comments, you can update multiple tables only if there are unique / primary key fields included in the view (this way Oracle knows which row to update)... Also you cannot obviously update those unique fields
guigui42
@Shaul, no - there must be exactly 1 "key-preserved" table in the subquery.
Tony Andrews
A: 
update MyTable t
set Col1 = (SELECT o.Col2 from OtherTable o
            WHERE t.OtherID = o.ID)
Michael Pakhantsov
Beware that this sets MyTable.Col1 to NULL if there is no match in OtherTable.
Tony Andrews
+3  A: 

Option A) A correlated subquery

UPDATE MyTable t
  SET Col1 = (SELECT o.col2 FROM OtherTable o WHERE t.OtherID = o.ID)

This requires that the subquery return no more than 1 match for each row in the table being updated. If it returns no match, the column will be updated with NULL, which may not be what you want. You could add WHERE EXISTS (SELECT o.col2 FROM OtherTable o WHERE t.OtherID = o.ID) to cause the update to only occur where a match is found.

Option B) Updating a join view

UPDATE (SELECT t.col1, o.col2 FROM MyTable t JOIN OtherTable o ON t.otherID = o.ID)
  SET col1 = col2

This is closer to what you are used to doing. It will only work if Oracle can determine a unique row in the underlying table for each row in the join -- which I think basically means that ID must be a unique key of otherTable.

Dave Costa
+1  A: 
update MyTable t
set Col1 = (SELECT o.Col2 from OtherTable o
            WHERE t.OtherID = o.ID)
where exists (SELECT o.Col2 from OtherTable o
            WHERE t.OtherID = o.ID)

The "where exists" part is to prevent col1 being set to NULL for MyTable rows that don't have a match in OtherTable - assuming this could happen and needs to be prevented.

Tony Andrews
+1  A: 

You can use a temporary table like so:

update
(
    select t.Col1, o.Col2
    from MyTable t
    join OtherTable o
        on t.OtherID = o.ID
) tmp
set tmp.Col1 = tmp.Col2
Aaron Digulla