Question

Is there a way to easily/elegantly update multiple columns in a table with record values from a query in Oracle 10g?

I have a table (call it Source) which has for simplicities sake, 2 columns, ID and KEY.

ID     Key
----   ---- 
1        1000
2        1000
3        5000
4        1000
..
101      8000
102      9000
103      7000
104      9000
...
201         5
202         5
...

I have another table (call it KeyMap) that takes trunc(ID/100) and uses it as a batchID with the columns being a key map for the IDs within the batch:

trunc(ID/100)   key1   key2   key3   key4 ..... key99
-------------   ----   ----   ----   ----
0               1000   1000   5000   1000
1               8000   9000   7000   9000
2                  5      5               

The ID's are created and processed in batches, so at the conclusion of the batch processing I would like to call a stored procedure to update the record in the KeyMap table with the new Key values with 1 update statement using a sub-select or collection providing those key values.

Is this possible and what is the best/most efficient way of doing this?

Was it helpful?

Solution

I'll limit my criticism to say that your table design is not normalized, and isn't very pretty, but I'll assume you have your reasons. I typically do these "rotation" queries by using DECODE combined with a aggregate column, grouping by my key - in this case, your pseudo-key, trunc(ID/100). Combine that with the update syntax that uses tuples:

 UPDATE Foo
    SET (a, b, c, d)
      = (w, x, y, z);

and you get:

  UPDATE KeyMap
     SET
       ( key1
       , key2
       , key3
       , key4
       ...
       , key99
       )
       = ( SELECT MAX(decode(mod(ID, 100), 1, Key, NULL))
                , MAX(decode(mod(ID, 100), 2, Key, NULL))
                , MAX(decode(mod(ID, 100), 3, Key, NULL))
                , MAX(decode(mod(ID, 100), 4, Key, NULL))
                ...
                , MAX(decode(mod(ID, 100), 99, Key, NULL))
             FROM Source
            WHERE Trunc(Source.ID / 100) = KeyMap.batchId
            GROUP BY Trunc(Source.ID / 100)
         )
   WHERE BatchId = <x>;

OTHER TIPS

you could generate an Oracle VARRAY and pass in your keys in a batch. your procedure could iterate over the VARRAY and update the table.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top