This very much depends on the data present in the table at the time of the UPDATE
.
If, for instance, the table has 1,000,000 rows where value1 = 'foo'
and only 1 row where value1 <> 'foo'
then UPDATE table1 SET value1='foo' WHERE value2='bar' AND value1 <> 'foo';
will only actually update a single row. Whereas UPDATE table1 SET value1='foo' WHERE value2='bar';
would update 1,000,001 rows.
If you are talking about a table with only two rows, the difference is entirely negligible.
If you were using SQL Server and had a filtered index like WHERE value2 = 'bar' AND value1 <> 'foo'
then UPDATE table1 SET value1='foo' WHERE value2='bar' AND value1 <> 'foo';
would most likely use the index instead of scanning the entire table.
Using the ranking ROW_NUMBER()
function will work. First give row numbers to all rows in both tables, then join using these row numbers, then update:
with
oldt as
( select fileNo , folder, fileType,
row_number() over (partition by fileNo, folder
order by fileType)
as rn
from oldtable
),
newt as
( select fileNo , folder, fileType,
row_number() over (partition by fileNo, folder
order by fileType)
as rn
from newtable
),
upd as
( select
n.fileType,
o.fileType as old_fileType
from newt n
join oldt o
on n.fileNo = o.fileNo
and n.folder = o.folder
and n.rn = o.rn
)
update
upd
set
fileType = old_fileType ;
SQLfiddle seems to be giving error for Oracle, so it has been tested in SQL Server only: SQLfiddle-test (but this syntax should be valid for Oracle, too).
Tested in Oracle, the above doesn't work, sadly. I think because statements that start with WITH
can only be SELECT
statements. Even if the query is rearranged (I tried several rewrites), Oracle throws various errors. The only way I managed to have it working is after adding another column in newtable
and a unique constraint on it. Then the following works (nid
is the added primary key column).
Tested in Oracle's Live SQL site:
update
( with
oldt as
( select fileNo , folder, fileType,
row_number() over (partition by fileNo, folder
order by fileType)
as rn
from oldtable
),
newt as
( select fileNo , folder, nid,
row_number() over (partition by fileNo, folder
order by fileType)
as rn
from newtable
),
upd as
( select
n.nid,
o.fileType as old_fileType
from newt n
join oldt o
on n.fileNo = o.fileNo
and n.folder = o.folder
and n.rn = o.rn
)
select
up.fileType,
( select upd.old_fileType
from upd
where upd.nid = up.nid
) as old_fileType
from newtable up
) x
set fileType = old_fileType ;
Best Answer
It would be helpful if you gave tables and columns, but something like this might work. Basically, move the WHERE into a case statement and set the column equal to itself if the condition is not met.