Is there a bulk update statement in 11g?

Hi everyone,
This is a pretty simple request but I cannot seem to find any documentation for it (at least on the 11g DB version).
I have a simple update statement:
UPDATE W_AP_XACT_FS SET DATASOURCE_NUM_ID = 5;
COMMIT;It probably seems strange why I would want to do that, but suffice it to say that I have no control over what value gets loaded into that column, however, I do need to correct it.
Either way, I want to make the above statement as efficient as possible.
What's the fastest way to perform a quick static update like that? Is there such a thing as a bulk update statement?
Thanks for the help!
-Joe

I need something that works 100% of the time and doesn't hang & create a DB lock.It has to lock the records it's updating until you commit. You could commit more frequently via a procedural approach but that is generally considered a bad idea because it's slower, takes more resources and risks 'snapshot too old' errors. 'Hanging' can mean a number of things, so I'm not sure which scenario you need to avoid here apart from the update taking a long time. Maybe it's just processing a lot of rows, in which case you might be able to throw some more resources at it with parallel DML. Or maybe it's blocked by another session, in which case you can find out a lot from v$session, v$lock, dba_blockers etc.
UPDATE W_AP_XACT_FS SET DATASOURCE_NUM_ID = 5;Could there ever be any rows prior to the update that already have DATASOURCE_NUM_ID = 5? If so, adding
WHERE datasource_num_id != 5;(if datasource_num_id is mandatory) or something like
WHERE datasource_num_id != 5
OR    datasource_num_id IS NULL;(if it's nullable) would reduce the number of rows needing to be processed.
Edited by: William Robertson on Aug 1, 2010 8:07 PM

Similar Messages

  • Need help to write a query for Update statement with  join

    Hi there,
    The following update statement gives me error as the given table in set statement is invalid. But its the right table .
    Is the statement correct? Please help .
    update (
           select distinct(vpproadside.VEHICLE_CRED_OVERRIDE.vin)            
             from vpproadside.VEHICLE_CRED_OVERRIDE
             join vpproadside.vpp_vehicle
               on vpproadside.vpp_vehicle.vin = vpproadside.VEHICLE_CRED_OVERRIDE.vin
            where VPP_CARRIER_SEQ_NUMBER = 90
              and EXPIRY_DATE = '17-MAR-10'
       set vpproadside.VEHICLE_CRED_OVERRIDE.EXPIRY_DATE = '15-SEP-10';Edited by: Indhu Ram on Mar 12, 2010 1:00 PM
    Edited by: Indhu Ram on Mar 12, 2010 1:22 PM
    Edited by: Indhu Ram on Mar 12, 2010 2:35 PM
    Edited by: Indhu Ram on Mar 15, 2010 8:04 AM
    Edited by: Indhu Ram on Mar 15, 2010 8:06 AM
    Edited by: Indhu Ram on Mar 15, 2010 8:28 AM

    Ask Tom has very good discussion about this, if UPDATE does not work for PK issue, you can use MERGE
    http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:760068400346785797

  • Problem in bulk update on partitioned table

    Hi,
    As per my old discussions on my huge table t_utr with 220 million rows,
    I'm running a bulk update statement on the table which may update 10 to 10 million rows in a single update statement.
    The problem is that when the statement has to update more number of rows, the update statement take more time.
    Here I want to know, when a update statement has to update more rows, will it impact the performance?
    Regards
    Deepak

    > I'm running a bulk update statement on the table
    which may update 10 to 10 million rows in a single
    update statement.
    Bulk updates does not make SQL statements execute any faster.
    > The problem is that when the statement has to update
    more number of rows, the update statement take more
    time.
    It is not a problem, but a fact.
    > Here I want to know, when a update statement has to
    update more rows, will it impact the performance?
    You have a car capable of traveling 120km/h. You drive from point A to point B. These are 10 km apart. It takes 5 minutes.
    Obviously when you travel from A to Z that are a 1000 km apart, it is going to take a lot longer than just 5 minutes.
    Will updating more rows impact performance? No. Because you cannot compare the time it takes to travel from point A to B with the time it takes to travel from point A to Z. It does not make sense wanting to compare the two. Or thinking that a 1000km journey will be as fast to travel than a 10km journey.
    Updating 10 rows cannot be compared to updating 10 million rows. Expecting a 10 million row update to be equivalent in "performance" to a 10 row update is ludicrous.
    The correct question to ask is how to optimise a 10 million row update. The optimisation methods for a large update is obviously very different than those of a small update. E.g. 5 I/Os per row updated is insignificant when updating 10 rows. But is very significant when updating 10 million rows.

  • [CS3] Is there a way to stop the modal alert on EVERY SINGLE ERROR during a bulk update?

    I've inherited quite a mess I'll admit -- I've got ~ 8000 pages each with different dreamweaver templates with the entire site being in a varying state of disrepair.  I need to perform a global change -- I'm thinking the way to go about this is to update the templates (thre are ~40 of them, not nested) and let the process run through. However, I've encountered difficulties.
    After about ~2300 files loaded into the site cache, dreamweaver crashes -- there is no error, it's an unhandled exception.... it consistently crashes at this point.  I'm not sure if this is a specific page causing the problem, or if it's that I'm trying to load 8K files into the site cache....  So anyway, with it crashing consistently trying to build the site cache, I basically press "stop" whenever it tries, and that seems to abort the building and the 'update pages' screen comes up and tries to update the files.
    My next problem is that there are countless errors in each of these pages and templates -- ranging from the 'template not found' when an old or outdated file is referencing a template that has been deleted -- to various mismatched head or body tags.  Of course, and this is probably the most annoying thing I've ever encountered,  this bulk process that should run over 1000s of files without interaction seems to feel the need to give me a modal alert for every single error.  The process stops until I press 'OK'
    I'm talking update 5-10 files, error... hit 'return', another 5-10 files are processed, another alert, hit 'return' -- rinse and repeat.  Oh, and I made the mistake one time of hitting 'return' one too many times -- oh yes, this will STOP the current update because default focus is on the 'Stop' button, for whatever reason. and if I want to get the rest of the files, I need to run it again -- from the start.
    Is there a way to silence these errors?   They're already showing up in the log, I wouldn't mind going through it once the entire site has been udpated to clean thing up ... but I'm updating quite literally thousands of pages here, I would wager that 1/3 of them have some form of an error on it... do I really need to press "OK" two thousand times to do a bulk update with this program?
    Any tips from the pros?

    This one might help.
    Allow configuration of Automatic Updates in Windows 8 and Windows Server 2012
    Regards, Dave Patrick ....
    Microsoft Certified Professional
    Microsoft MVP [Windows]
    Disclaimer: This posting is provided "AS IS" with no warranties or guarantees , and confers no rights.

  • Bulk SQL Update Statements

    I need to perform bulk updates on my tables using SQL. The tables are really very big and most of updates occur on couple of million records. As such the process is time consuming and very slow. Is there anything I could do to fine tune these update statements? Please advise. Some of the same SQL statements I use are as follows
    update test set gid=1 where gid is null and pid between 0 and 1;
    update test set gid=2 where gid is null and pid between 1 and 5;
    update test set gid=3 where gid is null and pid between 5 and 10;
    update test set gid=4 where gid is null and pid between 10 and 15;
    update test set gid=5 where gid is null and pid between 15 and 70;
    update test set gid=6 where gid is null and pid between 70 and 100;
    update test set gid=7 where gid is null and pid between 100 and 150;
    update test set gid=8 where gid is null and pid between 150 and 200;
    update test set gid=9 where gid is null and pid between 200 and 300;
    Message was edited by:
    user567669

    Indeed, check out the predicate:
    SQL> explain plan for
      2  select *
      3  from emp
      4  where sal between 1000 and 2000;
    Explained.
    SQL> @utlxpls
    PLAN_TABLE_OUTPUT
    Plan hash value: 3956160932
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT  |      |     5 |   185 |     3   (0)| 00:00:01 |
    |*  1 |  TABLE ACCESS FULL| EMP  |     5 |   185 |     3   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
    PLAN_TABLE_OUTPUT
       1 - filter("SAL"<=2000 AND "SAL">=1000)

  • Is there any System setting for Update statement

    Is there any setting for update statement related to implicit commit because Update statement in my code behaves differently in different systems.
    My code is
    Data:  it_eaus like eaus occurs 0 with header line,
            wa_eaus type eaus.
    select * from eaus into table it_eaus where auszbeleg = '000000000001'  and storausz = 'X'.
    if sy-subrc = 0 .
    wa_eaus-aedat = ''.
    wa_eaus-aenam = ''.
    wa_eaus-storausz = ''.
    modify it_eaus from wa_eaus transporting aedat aenam storausz where auszbeleg = '000000000001'.
    update eaus from table it_eaus.
    endif.
    Data:  it_eausv like eausv occurs 0 with header line,
            wa_eausv type eausv.
    select * from eausv into table it_eausv where auszbeleg = '000000000001'  and storausz = 'X'.
    if sy-subrc = 0 .
    wa_eausv-aedat = ''.
    wa_eausv-aenam = ''.
    wa_eausv-storausz = ''.
    modify it_eausv from wa_eausv transporting aedat aenam storausz where auszbeleg = '000000000001'.
    update eausv from table it_eausv.
    endif.

    Hi
    It isn't an alternative way: u can only explicit the COMMIT just as I said before:
    Update DBTAB set COL.
    COMMIT WORK.
    Anyway just I said before the debugger can execute a COMMIT, from SAP help:
    The New Debugger can run in exclusive and non-exclusive mode. Exclusive mode means that the application that is being analyzed exclusively occupies a work process of the application server during debugging. In non-exclusive mode, the Debugger functions are limited. In non-exclusive mode, after each Debugger interaction, the system requests a roll-out in the application. Therefore, an implicit database commit must be executed. This has the following consequences:
    u25CF      Debugging is not possible between the statements SELECTand ENDSELECTbecause the database cursor needs to be closed when using an implicit database COMMIT statement.
    In this case, program execution is terminated.
    ·        Debugging is not possible for conversion or field exits.
    ·        Due to the implicit database commit, inconsistent datasets can occur in the database.
    For this reason, non-exclusive mode is not possible in productive systems.
    Max

  • My wifi network is 802.11n but there are times changing for 802.11g, and have to restart ... after the update for Mountain Lion

    My wifi network is 802.11n but there are times changing for 802.11g, and have to restart ... after the update for Mountain Lion...  Help!!!
    Several problems with Mountain Lion, APP STORE (login/logout error), WIFI(802.11n for 802.11g), MAIL (horrible)... Apple, what is happening?   

    Do a factory reset .. nothing will be deleted from your backups and you will be able to get access to them again.
    The Factory Reset Gen1-4.
    Unplug your TC. Hold in reset. and power the TC back on.. without releasing reset for about 10sec. When the status light flashes rapidly; release it.
    Be Gentle! Feel the switch click on. It has a positive feel..  add no more pressure after that.
    TC will reboot after a couple of minutes with default factory settings and will wipe out previous configurations.
    No files are deleted on the hard disk.. No reset of the TC deletes files.. to do that you use erase from the airport utility.

  • Will there be a updated release of the 11g preview prior to the final ?

    so we can attempt to migrate some 10g apps.

    Rob,
    There's a forum for the 11g release BPEL
    Where if you look, you'll find this: Jdeveloper 11g Release?
    Where the short answer is "yes"
    John

  • How to convert the following FORALL Update to direct SQL UPDATE statement

    I have a FORALL loop to update a table. It is taking too long. I want to rewrite the code to a direct UPDATE sql. Also, any other tips or hints which can help run this proc faster?
    CURSOR cur_bst_tm IS
    SELECT listagg(tm, ' ') WITHIN GROUP(ORDER BY con_addr_id) best_time,
           con_addr_id
       FROM   (select Trim(Upper(con_addr_id)) con_addr_id,
                      ||decode(Initcap(start_day),
                                      'Monday', 'm',
                                    'Tuesday', 'tu',
                                    'Wednesday', 'w',
                                    'Thursday', 'th',
                                    'Friday', 'f',
                                     Initcap(start_day))
                      ||'='
                      ||trunc(( ( TO_DATE(start_tm,'HH12:MI:SS PM') - trunc(TO_DATE(start_tm,'HH12:MI:SS PM')) ) * 24 * 60 ))
                      ||','
                      ||trunc(( ( TO_DATE(end_tm,'HH12:MI:SS PM') - trunc(TO_DATE(end_tm,'HH12:MI:SS PM')) ) * 24 * 60 )) tm
               FROM   (SELECT DISTINCT * FROM ODS_IDL_EDGE_OFFC_BST_TM)
                 WHERE con_addr_id is not null)
      GROUP  BY con_addr_id
      ORDER BY con_addr_id;
    TYPE ARRAY IS TABLE OF cur_bst_tm%ROWTYPE;
    l_data ARRAY;
    BEGIN
    OPEN cur_bst_tm;
         LOOP
        FETCH cur_bst_tm BULK COLLECT INTO l_data LIMIT 1000;
        FORALL i IN 1..l_data.COUNT
          UPDATE ODS_CONTACTS_ADDR tgt
          SET best_times = l_data(i).best_time,
          ODW_UPD_BY = 'IDL - MASS MARKET',
           ODW_UPD_DT = SYSDATE,
          ODW_UPD_BATCH_ID = '0'
          WHERE Upper(edge_id) = l_data(i).con_addr_id
           AND EXISTS (SELECT 1 FROM ods_idl_edge_cont_xref src
                       WHERE tgt.contacts_odw_id = src.contacts_odw_id
                          AND src.pc_flg='Y')  
        EXIT WHEN cur_bst_tm%NOTFOUND;
        END LOOP;
      CLOSE cur_bst_tm;Record count:-
    select count(*) from
    ODS_IDL_EDGE_OFFC_BST_TM;
    140,000
    SELECT count(*)
    FROM ods_idl_edge_cont_xref src
    WHERE src.pc_flg='Y';
    118,000
    SELECT count(*)
    FROM ODS_CONTACTS_ADDR;
    671,925
    Database version 11g.
    Execution Plan for the update:
    Operation     Object Name     Rows     Bytes     Cost     Object Node     In/Out     PStart     PStop
    UPDATE STATEMENT Optimizer Mode=ALL_ROWS          6 K          8120                     
    UPDATE     ODW_OWN2.ODS_CONTACTS_ADDR                                   
    HASH JOIN SEMI          6 K     256 K     8120                     
    TABLE ACCESS FULL     ODW_OWN2.ODS_CONTACTS_ADDR     6 K     203 K     7181                     
    TABLE ACCESS FULL     ODW_OWN2.ODS_IDL_EDGE_CONT_XREF     118 K     922 K     938
    Edited by: user10566312 on May 14, 2012 1:07 AM

    The code tag should be in lower case like this {noformat}{noformat}. Otherwise your code format will be lost.
    Here is a update statementupdate ods_contacts_addr tgt
    set (
              best_times, odw_upd_by, odw_upd_dt, odw_upd_batch_id
         ) =
              select best_time, odw_upd_by, odw_upd_dt, odw_upd_batch_id
              from (
                   select listagg(tm, ' ') within group(order by con_addr_id) best_time,
                        'IDL - MASS MARKET' odw_upd_by,
                        sysdate odw_upd_dt,
                        '0' odw_upd_batch_id,
                        con_addr_id
                   from (
                             select Trim(Upper(con_addr_id)) con_addr_id,
                                  ||decode(Initcap(start_day), 'Monday', 'm', 'Tuesday', 'tu', 'Wednesday', 'w', 'Thursday', 'th', 'Friday', 'f', Initcap(start_day))
                                  ||'='
                                  ||trunc(((TO_DATE(start_tm,'HH12:MI:SS PM')-trunc(TO_DATE(start_tm,'HH12:MI:SS PM')))*24*60 ))
                                  ||','
                                  ||trunc(((TO_DATE(end_tm,'HH12:MI:SS PM')-trunc(TO_DATE(end_tm,'HH12:MI:SS PM')))*24*60)) tm
                             FROM (
                                  select distinct * from ods_idl_edge_offc_bst_tm
                             WHERE con_addr_id is not null
                   group
                   by con_addr_id
              where upper(tgt.edge_id) = con_addr_id
    where exists
              SELECT 1
              FROM ods_idl_edge_cont_xref src
              WHERE tgt.contacts_odw_id = src.contacts_odw_id
              AND src.pc_flg='Y'
    and exists
              select null
              from (
                   SELECT listagg(tm, ' ') WITHIN GROUP(ORDER BY con_addr_id) best_time,
                        'IDL - MASS MARKET' odw_upd_by,
                        SYSDATE odw_upd_dt,
                        '0' odw_upd_batch_id,
                        con_addr_id
                   FROM (
                             select Trim(Upper(con_addr_id)) con_addr_id,
                                  ||decode(Initcap(start_day), 'Monday', 'm', 'Tuesday', 'tu', 'Wednesday', 'w', 'Thursday', 'th', 'Friday', 'f', Initcap(start_day))
                                  ||'='
                                  ||trunc(((TO_DATE(start_tm,'HH12:MI:SS PM')-trunc(TO_DATE(start_tm,'HH12:MI:SS PM')))*24*60 ))
                                  ||','
                                  ||trunc(((TO_DATE(end_tm,'HH12:MI:SS PM')-trunc(TO_DATE(end_tm,'HH12:MI:SS PM')))*24*60)) tm
                             FROM (
                                  SELECT DISTINCT * FROM ODS_IDL_EDGE_OFFC_BST_TM
                             WHERE con_addr_id is not null
                   GROUP
                   BY con_addr_id
              where upper(tgt.edge_id) = con_addr_id
    This is an untested code. If there is any syntax error then please fix it and try.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

  • Running an update statement on two dependent attributes

    Dear All,
    I have a repair_job table that contains values for work_cost, parts_cost and total_cost which is the sum of the work and parts cost values. I want to run an update statement that doubles the work cost and, naturally, updates the value of total cost as well. I tried to run it as:
    update repair_job
    set work_cost = 2 * work_cost, total_cost = work_cost + parts_cost
    where licence in (
    select licence from car
    where year = to_char(sysdate,'YYYY')
    thinking that because the update of work_cost is first on the list, the updated value of total cost would be correct. It seems however that the update of total cost happens first and then the work cost is been updated; not sure what the reason is for that and it happens no matter what the order is in the update statement.
    I know that I can do it in two separate statements, or use a trigger or PL/SQL to do it but I am curious as to why it has this behaviour. Also, is there a way to do it in a single SQL statement - i.e. forcing the update of the work_cost attribute first and then that of total_cost?
    I look forward to hearing from you soon.
    Regards,
    George

    Welcome to the forum!
    >
    thinking that because the update of work_cost is first on the list, the updated value of total cost would be correct. It seems however that the update of total cost happens first and then the work cost is been updated; not sure what the reason is for that and it happens no matter what the order is in the update statement.
    I know that I can do it in two separate statements, or use a trigger or PL/SQL to do it but I am curious as to why it has this behaviour. Also, is there a way to do it in a single SQL statement - i.e. forcing the update of the work_cost attribute first and then that of total_cost?
    >
    The update to all columns of the row happen at the same time - there is no order involved.
    You don't need two statements but you do need to do the updates based on the current value of the columns.
    set work_cost = 2 * work_cost, total_cost = 2 * work_cost + parts_cost----------
    In addition to sb92075's comments in 11 g you could also just define a virtual column for total_cost and then just query it like you do now.
    total_cost   NUMBER GENERATED ALWAYS AS (work_cost + parts_cost) VIRTUAL,See this Oracle-base article for an example
    http://www.oracle-base.com/articles/11g/virtual-columns-11gr1.php
    Edited to supplement sb92075's reply by mentioning virtual columns

  • ROWCOUNT in BULK Insert Statement

    Hi,
    I'm using in a BULK INSERT statement in a PL/SQL procedure and after execution of the SQL statement,I need to capture the row count.
    Same is the case for UPDATE.
    The Example code is as mentioned below:
    INSERT INTO TBL1
    (SELECT VAL1,VAL2 FROM TBL2)
    No. of rows inserted needs to be retrieved after execution of this SQL.
    Please let me know if there is any way to do it.
    Thanks.

    SQL> create table emp as select * from scott.emp where 1 = 0 ;
    Table created.
    SQL> set serveroutput on
    SQL> begin
      2    insert into emp select * from scott.emp ;
      3    dbms_output.put_line('Count='||SQL%RowCount) ;
      4  end ;
      5  /
    Count=14
    PL/SQL procedure successfully completed.
    SQL>

  • Performance Issue: Update Statement

    Hi Team,
    My current environment is Oracle 11g Rac...
    My application team is executing a update statement (ofcourse it is there daily activity) ...
    updating rows of 1 lac, daily it takes about 3-4 minutes to run the statement.
    But today its taking more time i.e more than 8 hours.
    then I have generated the explain plan of the update statement and found that its taking full table scan.
    Kindly assist me in fixing the issue by letting me know where and how to look for the problem.
    **Note: Stats gather is updated
    Thanks in advance.
    Regards

    If you notice there are no indexes to the below update statement -
    UPDATE REMEDY_JOURNALS_FACT SET JNL_CREATED_BY_IDENTITY_KEY = ?, JNL_CREATED_BY_HR_KEY = ?, JNL_CREATED_BY_NTWRK_KEY = ?, JNL_MODIFIED_BY_IDENTITY_KEY = ?, JNL_MODIFIED_BY_HR_KEY = ?, JNL_MODIFIED_BY_NTWRK_KEY = ?, JNL_ASSGN_TO_IDENTITY_KEY = ?, JNL_ASSGN_TO_HR_KEY = ?, JNL_ASSGN_TO_NTWRK_KEY = ?, JNL_REMEDY_STATUS_KEY = ?, JOURNALID = ?, JNL_DATE_CREATED = ?, JNL_DATE_MODIFIED = ?, ENTRYTYPE = ?, TMPTEMPDATETIME1 = ?, RELATEDFORMNAME = ?, RELATED_RECORDID = ?, RELATEDFORMKEYWORD = ?, TMPRELATEDRECORDID = ?, ACCESS_X = ?, JOURNAL_TEXT = ?, DATE_X = ?, SHORTDESCRIPTION = ?, TMPCREATEDBY = ?, TMPCREATE_DATE = ?, TMPLASTMODIFIEDBY = ?, TMPMODIFIEDDATE = ?, TMPJOURNALID = ?, JNL_JOURNALTYPE = ?, COPIEDTOWORKLOG = ?, PRIVATE = ?, RELATEDKEYSTONEID = ?, URLLOCATION = ?, ASSIGNEEGROUP = ?, LAST_UPDATE_DT = ? WHERE REMEDY_JOURNALS_KEY = ?
    Explain Plan -
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
    | 0 | UPDATE STATEMENT | | | | 1055 (100)| | | | | | |
    | 1 | UPDATE | REMEDY_JOURNALS_FACT | | | | | | | | | |
    | 2 | PX COORDINATOR | | | | | | | | | | |
    | 3 | PX SEND QC (RANDOM) | :TQ10000 | 1 | 784 | 1055 (1)| 00:00:05 | | | Q1,00 | P->S | QC (RAND) |
    | 4 | PX BLOCK ITERATOR | | 1 | 784 | 1055 (1)| 00:00:05 | 1 | 10 | Q1,00 | PCWC | |
    |* 5 | TABLE ACCESS STORAGE FULL| REMEDY_JOURNALS_FACT | 1 | 784 | 1055 (1)| 00:00:05 | 1 | 10 | Q1,00 | PCWP | |
    Predicate Information (identified by operation id):
    5 - storage(:Z>=:Z AND :Z<=:Z AND "REMEDY_JOURNALS_KEY"=:36) filter("REMEDY_JOURNALS_KEY"=:36)
    Note
    - automatic DOP: skipped because of IO calibrate statistics are missing
    Edited by: GeetaM on Aug 17, 2012 2:18 PM

  • Update statement using case

    Hello my friends
    I have one table "encompasses": continent,country,percentage
    now the update should change the continent field, all "Europe" to "Asia" and all "Asia" to "America" and "America" to "Europe" by using case and just one update statement.
    I wrote so and i got this error
    Error starting at line 2 in command:
    UPDATE encompasses
       SET continent=    
          CASE  WHEN continent='Europe'  THEN 'Asia'  
          WHEN continent='Asia'  THEN 'America' 
          WHEN continent='America' THEN 'Europe'
          END
    Error report:
    SQL Error: ORA-01407: cannot update ("intern"."ENCOMPASSES"."CONTINENT") to NULL
    01407. 00000 -  "cannot update (%s) to NULL"
    *Cause:   
    *Action:please give me hints,thank u.
    --  File created - Monday-May-13-2013  
      CREATE TABLE "intern"."ENCOMPASSES" ("COUNTRY" CHAR(2), "CONTINENT" VARCHAR2(20), "PERCENTAGE" NUMBER)
       COMMENT ON COLUMN "intern"."ENCOMPASSES"."COUNTRY" IS 'the country code'
       COMMENT ON COLUMN "intern"."ENCOMPASSES"."CONTINENT" IS 'the continent name'
       COMMENT ON COLUMN "intern"."ENCOMPASSES"."PERCENTAGE" IS 'percentage, how much of the area of a country belongs to the
                continent'
       COMMENT ON TABLE "intern"."ENCOMPASSES"  IS 'information to which continents a country belongs'
    REM INSERTING into intern.ENCOMPASSES
    SET DEFINE OFF;
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('cx','Asia',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('eg','Asia',10);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('ge','Asia',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('id','Asia',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('ad','Europe',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('al','Europe',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('at','Europe',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('ba','Europe',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('pa','America',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('pe','America',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('pm','America',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('pr','America',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('py','America',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('sr','America',100);
    Insert into intern.ENCOMPASSES (COUNTRY,CONTINENT,PERCENTAGE) values ('sv','America',100);thank you, im using oracle 11g and ubuntu12
    best,david
    Edited by: 1003209 on 13-May-2013 10:12

    1003209 wrote:
    Hello my friends
    I have one table "encompasses": continent,country,percentage
    now the update should change the continent field, all "Europe" to "Asia" and all "Asia" to "America" and "America" to "Europe" by using case and just one update statement.
    I wrote so and i got this error
    Error starting at line 2 in command:
    UPDATE encompasses
        SET continent=    
           CASE  WHEN continent='Europe'  THEN 'Asia'  
           WHEN continent='Asia'  THEN 'America' 
           WHEN continent='America' THEN 'Europe'
           END
    Error report:
    SQL Error: ORA-01407: cannot update ("intern"."ENCOMPASSES"."CONTINENT") to NULL
    01407. 00000 -  "cannot update (%s) to NULL"
    *Cause:   
    *Action:This seems the column Continent has not null contraint on it, hence when there is a continent other than the three you mentioned above the case statement is evaluating it to null and hence failing e.g. if there is a record with continent = 'Antartica' it will try to update that as null.
    so either add this:
    WHERE continent in ('Europe' ,'Asia','America')this will update only for this continents and ignore other values.
    If you want to update other continents as well then have a else condition in CASE statement to assign defualt value.
    Regards,
    Santosh

  • Bulk Update query

    Hello Friends,
    Can some one suggest me is that any possible bulk update query which consumes less timings?
    Table - MyTable
    id - PK.
    orderid - Order Id.
    Subid - Sub Id for an Order.
    lineitem - LineItemId.
    ProducId - Product Id.
    Now i want to update the Subid to My Table for Every Order on Basis of LineItemId..
    For Ex:
    I will be having the records in MyTable as for a single Order...there can mutilple Subid's.
    UPDATE MyTable SET subid = 1 WHERE orderid = 123 AND lineitem = 1;
    UPDATE MyTable SET subid = 1 WHERE orderid = 123 AND lineitem = 2;
    UPDATE MyTable SET subid = 5 WHERE orderid = 123 AND lineitem = 2000;
    I worked out three scenarios as follows,
    Case1:
    UPDATE MyTable SET subid = 5 WHERE orderid = 123 AND lineitem = 2000;
    Case2:
    UPDATE MyTable SET subid = 1 WHERE orderid = 123 AND lineitem in(1,2,3.....1000);
    UPDATE MyTable SET subid = 2 WHERE orderid = 123 AND lineitem in(1001,1002,.....1100);
    Case3:
    UPDATE MyTable SET subid= CASE WHEN lineitem = 1 THEN 1 WHEN lineitem = 2 THEN 2 .....WHEN 1000 THEN 1000 END WHERE orderid = 123;
    Please suggest me which update consumes less time and helpful for updating more records nearly 5000 - 10000 at a single table.

    You are comparing three cases that are not equal to each other:
    Case1:
    UPDATE MyTable SET subid = 5 WHERE orderid = 123 AND lineitem = 2000;
    Here you update the records with orderid = 123 and lineitem = 2000
    Case2:
    UPDATE MyTable SET subid = 1 WHERE orderid = 123 AND lineitem in(1,2,3.....1000);
    UPDATE MyTable SET subid = 2 WHERE orderid = 123 AND lineitem in(1001,1002,.....1100);
    This are multiple update statement to update all records with orderid = 123 and lineitems between 1 and 1100.
    Case3:
    UPDATE MyTable SET subid= CASE WHEN lineitem = 1 THEN 1 WHEN lineitem = 2 THEN 2 .....WHEN 1000 THEN 1000 END WHERE orderid = 123;
    And here all records with orderid = 123, regardless of the lineitem are updated.
    So my guess is that 1 will be the fastest as it is updating the least amount of records, followed by 2 and then 3. But it is a really weird comparison.
    I think you'd better make up your mind first about which records need to be updated and how. And then it is best to use one update statement to do the job.
    Regards,
    Rob.

  • How to tune this update statement?

    Hello,
    I have to solve the following task:
    Update every row in table A which has an appropriate row in table B and log what you have done in a log-table.
    It is possible that there are more than one fitting rows in table A for a row in table B.
    My first approach is looping over the table B and doing an update of table A for every entry in table B.
    This works and looks like this:
    Table A:
    PK number (This is the primary key of this table)
    KEY number
    Table B:
    KEY_OLD number
    KEY_NEW number
    Log table:
    PK number
    KEY_OLD number
    KEY_NEW number
    declare
      TYPE PK_TAB_TYPE IS TABLE OF number INDEX BY BINARY_INTEGER;
      v_tab_PK       PK_TAB_TYPE;
      v_empty_tab_PK PK_TAB_TYPE;
    begin
      for v_rec in (select * from table_B) loop
        v_tab_PK := v_empty_tab_PK;  /* clearing the array */
        update table_A
        set    KEY = v_rec.KEY_NEW
        where (KEY = v_rec.KEY_OLD)
        returning PK bulk collect into v_tab_PK;
        if (v_tab_PK.count > 0) then
          for i in v_tab_PK.first..v_tab_PK.last loop
            insert into TMP_TAB_LOG(PK, KEY_OLD, KEY_NEW)
              values (v_tab_PK(i), v_rec.KEY_OLD, v_rec.KEY_NEW);
          end loop;
        end if;
      end loop;
    end;Because the table B can have up to 500.000 entries (and the table A has even more entries) this solution will cause many update-statements.
    So I am looking for a solution which has better performance.
    My second approach was using an correlated update and looks like this:
    declare
      TYPE PK_TAB_TYPE IS TABLE OF number INDEX BY BINARY_INTEGER;
      v_tab_PK            PK_TAB_TYPE;
      v_empty_tab_PK PK_TAB_TYPE;
      v_tab_NewKey    PK_TAB_TYPE;
    begin
      v_tab_PK         := v_empty_tab_PK;  /* clear the arrays */
      v_tab_NewKey := v_empty_tab_PK;
      update table_A a
      set    KEY = (select KEY_NEW from table_B where (KEY_OLD = a.KEY))
      where exists (select 'x' as OK
                         from   table_B
                         where (KEY_OLD = a.KEY)
      returning PK, KEY bulk collect into v_tab_PK, v_tab_NewKey;
      if (v_tab_PK.count > 0) then
        for i in v_tab_PK.first..v_tab_PK.last loop
          insert into TMP_TAB_LOG_DUB(PK, KEY_OLD, KEY_NEW)
            values (v_tab_PK(i), null, v_tab_NewKey(i));
        end loop;
      end if;
    end;Now I have only one update statement.
    The only thing missing in this second approach is the old KEY before the update in the log table.
    But I have no idea how to get the old value.
    Is there a possibility to modify this second approach to get the old value of the KEY before the update to write it in the log-table?
    And now I need your help:
    What is the best way to get a performant solution for my task?
    Every help appreciated.
    Regards Hartmut

    Below is a script you can run in another testing schema to do the update with logging..... I have created the tables (A and B) with primary key constraints defined...
    create table table_a(pk number primary key
    , key number);
    create table table_b(key_old number primary key
    , key_new number);
    create table TMP_TAB_LOG_DUB(pk number primary key
    , key_old number
    , key_new number);
    ---------insert test data
    insert into table_a values(1,2);
    insert into table_a values(2,2);
    insert into table_a values(3,2);
    insert into table_a values(11,1);
    insert into table_a values(12,1);
    insert into table_a values(13,1);
    insert into table_a values(21,4);
    insert into table_a values(22,4);
    insert into table_a values(23,4);
    commit;
    insert into table_b values(1,3);
    insert into table_b values(4,2);
    commit;
    ----- insert to log
    insert into TMP_TAB_LOG_DUB(PK, KEY_OLD, KEY_NEW)
    select a.pk
    , a.key as key_old
    , b.key_new as key_new
    from table_a a
    join table_b b on a.key = b.key_old;
    ----- update table_a
    update(select a.pk
    , a.key as key_old
    , b.key_new as key_new
    from table_a a
    join table_b b on a.key = b.key_old)
    set key_old = key_new;
    commit;

Maybe you are looking for