sql - UPDATE statement: re-evaluate subquery after each SET -


create table test (id number(3));  insert test values (1); insert test values (2); insert test values (2); insert test values (3); insert test values (4); insert test values (4); insert test values (5); 

i want make numbers in test unique (like {1,2,3,4,5,6,7} - i.e. remove doubles) using query:

update test u set u.id = (select max(nn.id) test nn) + 1    1 < (     select tt.rown        (select rowid, row_number() on ( partition t.id order t.id) rown test t) tt       tt.rowid = u.rowid     );  

the above query updates table {1,2,3,4,5,6,6}. replaces second 2 6 correctly, second 4 becomes 6 also, should 7. existing non-duplicates should not replaced, second-onward duplicates.

the problem above update statement (select max(nn.id) test nn) evaluated once , cached, depends on updated. possible force re-evaluation of (select max(nn.id) test nn) after each set? tried hints /*+nocache*/ without success.

in other words, during update, need take account fields have been updated.

anyone ideas?

i assume solved non-deterministic function, don't want make functions. edit: if try compute id function ora-04091: table test mutating, trigger/function may not see it. using pragma autonomous_transaction; gives same result above query.

solution precalculated ids, bypassing query re_evaluation

audriym solved (cf. comments) ms sql server 2008 using ctes. there no alternative in oracle ctes far know, because audriym's solution based on precalculated values ids, though translate in oracle subqueries. , here is:

update test u set u.id = ( select newids.newid                            ( select  ranked.rowid,                                           ranked.m + row_number() on (order ranked.id, ranked.r) newid                                    ( select t.rowid, t.id, row_number() on ( partition t.id order t.id) r, max(id) over() m                                          test t ) ranked                                   ranked.r > 1 ) newids                            u.rowid = newids.rowid ) u.rowid in ( select ranked.rowid                    ( select t.rowid, t.id, row_number() on ( partition t.id order t.id) r, max(id) over() m                            test t ) ranked                    ranked.r > 1 ); 

solution without precalculated ids, using query re_evaluation

still not found , question remains unanswered.

try use following statement. table doesn't allow identify row example id=2 link table row_number can use rowid

update test  set id = (select rn                      (select row_number()                               on (order id) rn                               test                      ) t1                      t1.rowid=test.rowid           ) 

sqlfiddle demo


Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

thorough guide for profiling racket code -