MERGE statement - delete all lines?

Hi all

I am using Oracle 11 g and in my application, I need to update several existing records in a table in the Production environment. For this, I wrote a SQL logic using the "MERGE INTO" statement.

Here's the SQL logic that I used.

merge into the tar of the target

a_l'_aide_de)

Select

EC.prim_id,

CSM.Cptr,

CSM.prm,

CSM.scnd,

CSM. PTXT,

CSM.entn,

CSM. ENPR,

CSM.sevr

t2 t1 ec cat inner join

on ec.x = cat.y

inner join s t3

on ec.p = q.a.

inner join t3 b

on ec.m = b.n

inner join t4 csm

on)

(lower (replace (cat.xn, b.sname |))) ((('-', ")) = lower (csm.xn))

and (below (replace (s.yn, b.sname |))) ((('-', ")) = lower (csm.yn))

and (lower (b.rn) = lower (csm.rn))

)

where ec.cptr is null

and ec.prm is null

and ec.scnd is null

and ec.ptxt is null

and ec.stxt is null

and ec.entn is null

and ec.enpr is null

and ec.sevr is null

) CBC

on)

SRC.prim_id = tar.prim_id

)

When matched then update

Set tar.cptr = src.cptr,

tar.PRM = src.prm,

tar.scnd = src.scnd,

tar. PTXT = src.plcy_txt,

tar. MID = "offline."

tar.entn = src.entn,

tar. ENPR = src.enpr,

tar.sevr = src.sevr

I doubt here, that is, if the condition WE in education MERGE gets failed then is it insert/delete all records in/to from the target table. But I think that it won't happen because I'm not specify the statement as 'WHEN DO NOT MATCHED THEN' right? Or default oracle will insert/remove all lines if the condition does not. ???

Your help is very appreciated.

Thanks in advance

If your question is addressed, then close this thread.

Tags: Database

Similar Questions

  • Delete all lines

    Hi all

    I am using jd 11.1.2.0

    I have a table that displays rows in a table. I want to delete all rows in the table when the user presses the button Delete

    Please tel me how to

    Thaks

    It should work with you

        public String deleteAll() {
            // Add event code here...
            DCBindingContainer bc = (DCBindingContainer)getBindings();
    
            // 2. Find a named iterator binding
            DCIteratorBinding iter = (DCIteratorBinding)bc.findIteratorBinding("TestView1Iterator");
    
            //4. Get the RowSetIterator Object
            RowSetIterator rsi = iter.getViewObject().createRowSetIterator(null);
            rsi.reset();
    
            //delete all rows
            while (rsi.hasNext()) {
                Row current = rsi.next();
                rsi.setCurrentRow(current);
                current.remove();
            }
    
             rsi.closeRowSetIterator();
    
            return null;
        }
    
  • Delete all line break tags

    I have a page that contains approximately 100 line breaks that I have to delete. How can I do this quickly?

    Is there a way to return an article or page in plain text so have also several tags I need deleted?

    Find and replace (Ctrl + F).
    Research > current Document > Source Code

    --
    Nancy O.
    ALT-Web Design & Publishing
    www.Alt-Web.com

  • Remove all lines and insert them into Oracle can make performance worse?

    I m working in a project that I need to make a batch update regularly (every 4 months) of excel files. These files have doesn´t excellent key in their ranks.

    The development of a code that deletes all lines and inserts the entire base again is easier than one who checks in all the ranks of its primary key and if necessary update. (sometimes may be a key to 5 columns).

    My question is: if I delete all the rows in the tables of the insert it again, it will cause tablespace fragmentation and in a future loss of performance?

    Is there a way to avoid this?

    Thanks in advance

    Alexander

    This response helped me a lot.

    Thank you all

    Remove all lines and insert them into Oracle can make performance worse? -Stack overflow

  • Is DELETE ALL really how you commit a snapshot?

    Greetings,

    I'm under ESXI 5.1. I want to take the current state of my VM and make permanent state, delete all the snapshots taken before. In my view, this is called "Commit" according to VMware. I thought it would be identical to "Consolidate", but I don't it is.

    Then, according to VMWare link below, to validate you just click "remove all" in the Snapshot Manager. This seems really shady and scary. Is this true?

    http://KB.VMware.com/selfservice/microsites/search.do?language=en_US & cmd = displayKC & externalId = 1026380

    That's right

    How to use snapshots of VMware using the GUI - YouTube

  • Delete all the snapshots State hooked up to 95%

    Any ideas why my task to delete all the snapshots status is attached to 95%?  It has been like that for a few hours.  I had 7 sequential shots that I need to remove to create space on my data store.  My data store's display file snapshot of 28,04 KB.  I need to make a new snapshot of my server, but do not know if it is safe to proceed since my first task to delete all snapshots do not show a State of complete.  Any ideas or help someone?

    This is normal, especially if you have a lot of drive to commit.  Once completed, you should be ok.

    http://KB.VMware.com/kb/1007566

  • Do I need a merge statement?

    My report looks like this:
    Sales Report For Business Date 9-12-2009
    ---------------------------------------- 
    StoreId                             121
    BusinessDate                        15-Aug-2009
    DailySales                          1009.00
    DailyGuest                           123
    DailyIngrdientsCost                  20.00
    --- Mustard           10.00
    --- Ketchup           5.00
    --- Mayonaisse       5.00
    DlyDrinkSales                        120.00
    I have 3 provisions of tables where the data comes from:
    ---=== Contains sales data for each day
    CREATE TABLE  SalesData  (
    ,  StoreId  NUMBER NOT NULL, 
    ,  BusinessDate Date
    ,  Sales Number
    ,  Guests  number
    ,  DrinkSales number)
    CREATE TABLE  Ingredients (
       BusinessDate Date
    ,   StoreID number
    ,   IngredientsCost Number 
    ,    MyForeighKey number 
    )
    --== MyForeignKey = PrimaryKey
    -- ===PrimaryKey is not unique
    Create Table IndividualIngredients
    (   
          PrimaryKey    Number  
        , Ingredient    nvarchar
        ,  Cost           number 
    )   
     
    ; My request for
    Select sd.StoreId
    ,      sd.BusinessDate
    ,      sd.ales
    ,      sd.Guests
    ,       sd.DrinkSales 
    ,       MainIng.ingredientsCost
    --=== Her should be the subIngredients and their cost ; number of ingredients is dynamic
    ,     '...' + Ind.Mustard   as Mustard
    ,    '...' +  Ind.Mayonaisse as Mayonnaise
    ,    '...' +  Ind.Ketchup as Ketchup
    -- The number of ingredients is dynamic
    , DlyDrinkSales
    From SalesData SD
    inner join Ingredients  MainIng on MainIng.storeid = SD.storeid                           
    inner join IndividualIngredients Ind on ind.primaryKey = MainIng.MyForeighKey
    where    MainIng.businessDate = sd.businssDate
    Of course, it gives me a daily statement by ingredient. How to achieve this? A merger is necessary? IM using Oracle 10 g

    Published by: user651380 on October 5, 2009 16:31

    Hello

    user651380 wrote:
    This was very helpful. I had too simplified my request as you can see in my example, and when I tried to incorporate, I got:
    C.n
    *
    ERROR on line 28:
    ORA-01790: expression must have same type of data, matching expression

    The two branches of the UNION must have the same types of columns.
    The data column (that is, the 2nd column) in the first part of the UNION is a VARCHAR2, but the data in the second column is a NUMBER.
    In the "simplistic" problem, this part was actually more complex. You were displaying a DATE and numbers together in the same column; the only way to do was to convert them all to VARCHAR2. It looks that you no longer have a DATE in this column, so you can delete all the TO_CHARs in the first part of the UNION and have given uniformly be a NUMBER, or add TO_CHAR the second part of the UNION, so that the data is always VARCHAR2. something like that

    UNION ALL
    --
    select   description
           , TO_CHAR ( prev_delv_cost   +  transfer_in_cost +  delv_cost   -  transfer_out_cost  - total_cost
                     , '999990.00'
                     ) as data
    

    ...
    WHEN 5 THEN TO_CHAR (t.net_food, ' 999990.00' ")
    WHEN 6 THEN TO_CHAR (T.b. & LSales', ' 999990.00' ")
    The END AS data
    c.n AS InvisibleSort
    C of the Cntr
    CROSS JOIN TargetStore t
    --
    UNION ALL
    --
    Select the description
    prev_delv_cost + transfer_in_cost + delv_cost - transfer_out_cost - as total_cost form data
    -= == do not know why you use 5.5
    5.5 AS InvisibleSort

    I used 5.5 to make individual ingredients come after DailyIngredientCost (which had a value of 5) and DlyDrinkSales (which was 6), you indicated that you wanted. I found which is easier than ignoring the number 6 and using 7 instead.

    A few questions:
    (1) how to avoid prompt when the field contains a '& '?

    If you don't use a proxy, the simplest thing is SQL * more order

    SET  DEFINE  OFF
    

    who will be disable them for your SQL * Plus the term and make '&' a normal character.

    (2) can you embed a With statement in a With statement.

    Yes, but I'm not there is no reason to. It is simpler just have all the subqueries you need into one WITH the clause.
    For example:

    WITH  a  AS
    (
        SELECT  col1, col2, RANK () OVER ... AS rnk
        FROM    table_x
        WHERE   ...
    )
    ,     b  AS
    (
        SELECT  col1, col2
        FROM    a
        WHERE   rnk <= ...
    )
    ,     c  AS
    (
        SELECT  a.col1, b.col1
        FROM    a
        JOIN    b     ON  a.col2 = b.col2
    )
    ...
    

    Note that b of the subquery refers to a and c refers to both a and b.

    I can do simple selects the main query and avoid having to
    program around the 10 fields that are not functions of the group. It is clear.

    No, sorry.

    In other words, in my main select, I would have already summarized fields.

    Are you talking about doing a GROUP BY in a subquery and then joining the results later? Yes, you can do it.
    As always, it would be better to show a practical example, with CREATE TABLE and INSERT statements for some examples of data and the results desired from these data. Simplify if possible. For example, if there are 10 similar columns, just the Terminal 2 and explain "there are really more than 8 columns like these 2...".

  • Different result by using the MERGE statement

    I have 2 SQL statements:

    MERGE INTO PT_CQS_AGGR APC

    With the HELP of PT_CQS_AGGR_TEMP Lady

    WE (concat (concat(pca.from_city_id,pca.to_city_id), pca.query_timestamp_hh) = concat (concat(pcah.from_city_id,pcah.to_city_id), pcah.query_timestamp_hh))

    WHEN MATCHED THEN

    Setting a DAY SET pca.search_count = pca.search_count + pcah.search_count

    WHEN NOT MATCHED THEN

    VALUES of INSERTION (to_city_id, query_timestamp_hh, from_city_id, search_count) (pcah.from_city_id, pcah.to_city_id, pcah.query_timestamp_hh, pcah.search_count);

    AND

    MERGE INTO PT_CQS_AGGR APC

    With the HELP of PT_CQS_AGGR_TEMP Lady

    WE (pca.from_city_id = pcah.from_city_id AND pca.to_city_id = pcah.to_city_id AND pca.query_timestamp_hh = pcah.query_timestamp_hh)

    WHEN MATCHED THEN

    Setting a DAY SET pca.search_count = pca.search_count + pcah.search_count

    WHEN NOT MATCHED THEN

    VALUES of INSERTION (to_city_id, query_timestamp_hh, from_city_id, search_count) (pcah.from_city_id, pcah.to_city_id, pcah.query_timestamp_hh, pcah.search_count);

    First statement correctly the merged data, but use FULL TABLE SCANS, so it's rather slow. Second statement using a UNIQUE INDEX on the columns from_city_id, to_city_id, and query_timestamp_hh on the MAP of EXPLAIN, but during the execution of I've got ORA-00001: unique constraint (PODOWNER. IDX_CQS_AGGR_3COL) violated. What is the problem with the second statement - especially with this line:

    WE (pca.from_city_id = pcah.from_city_id AND pca.to_city_id = pcah.to_city_id AND pca.query_timestamp_hh = pcah.query_timestamp_hh)

    Can I use a more complex condition in the MERGE statement? Because it seems that not all the conditions have been taken...

    ???

    Select pcah.from_city_id, pcah.to_city_id, PT_CQS_AGGR_TEMP Lady pcah.query_timestamp_hh

    less

    Select pca.from_city_id, pca.to_city_id, pca.query_timestamp_hh PT_CQS_AGGR pca

    somewhere the conditions limiting the time.

    (or whatever the columns make up the stress of failing)

    In addition, select for each column in the constraint of failure where the column is null.  If one of these columns is null, equality fails, even if both are null, because null <> null.  So you will get a "no match" if all values are the same and it is set to null.

    Edit: Oh, slap forehead, that is why one works and the complete analysis.  As SomeoneElse said, it normalizes the type of data and concatenates, comparison null to no effect and refusing all usual index.

  • Debugging this merge statement

    EMPL of MERGE IN one

    USING (SELECT *)

    T) b

    WE (a.empno = b.empno)

    WHEN MATCHED THEN

    UPDATE

    SET a.ename = b.ename, a.job = b.job,

    a.Mgr = b.mgr, a.hiredate = b.hiredate, a.sal = b.sal,

    a.comm b.com, a.deptno = b.deptno =

    WHEN NOT MATCHED THEN

    INSERT (a.empno, a.ename, a.job, a.mgr, a.hiredate, a.sal, a.comm,

    a.DEPTNO)

    VALUES (b.empno, b.ename, b.job, b.mgr, b.hiredate, b.sal, b.b.a., specialization

    b.DEPTNO);

    Note t is import table that has data of new employees and empl is the table that store data for all employees and it is the main table, above 2 tables are replica of scott.emp with data

    Problem when I'm executing the merge statement preceding the session is the gel

    Solution ?

    Perhaps another session has locked some rows in the emp table?

    Try

    select * from empl where empno in (select empno from t_imp) for update nowait;
    

    When you get an error such as ORA-00054, another session is locking of lines that you want to update.

    Hope that helps,

    dhalek

  • Get error in the merge statement

    Version of Oracle, Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production
    Hi gurus

    I am trying to perform the merge statement using the clause, but I get the error message, see below my sample data:

    Examples of data

    DROP TABLE OF BILLING;

    DROP TABLE GROUP_MST;

    DROP TABLE age_max;

    CREATE ARRAY OF BILLING

    (

    BILLING_ID NUMBER (5),

    RATE NUMBER (5),

    MAXIMUM_AGE NUMBER (5),

    package_id NUMBER (5)

    );

    INSERT

    IN BILLING

    (SELECT 11,1,10,100 FROM DUAL

    UNION ALL

    SELECT 12,2,15,100 FROM DUAL

    UNION ALL

    SELECT 13,3,20,100 FROM DUAL

    );

    CREATE TABLE GROUP_MST

    (group_number NUMBER (5), package_id NUMBER (5))

    );

    INSERT INTO GROUP_MST

    (SELECT DOUBLE 5 000 100

    );

    -------

    CREATE TABLE AGE_MAX

    (group_number NUMBER (5), max_age NUMBER (5))

    );

    INSERT

    IN AGE_MAX

    (SELECT 5000,60 FROM DUAL

    );

    Merge statement

    MERGE INTO DRC USING billing

    (WITH datum1 AS

    (SELECT A.group_number,

    b.billing_id,

    b.rate,

    b.maximum_age,

    b.package_id

    OF group_mst A,.

    b billing

    WHERE A.package_id = b.package_id

    ),

    datum2 AS

    (SELECT max_age, group_number FROM age_max

    )

    SELECT * FROM A, b WHERE A.group_number = b.group_number datum2 datum1

    )

    CBC ON (drc.billing_id = src.billing_id)

    WHEN MATCHED THEN

    UPDATE SET drc.maximum_age = src.max_age - 1;

    Error

    Error from the 33 in the command line:

    MERGE INTO DRC USING billing

    (WITH datum1 AS

    (SELECT A.group_number,

    b.billing_id,

    b.rate,

    b.maximum_age,

    b.package_id

    OF group_mst A,.

    b billing

    WHERE A.package_id = b.package_id

    ),

    datum2 AS

    (SELECT max_age, group_number FROM age_max

    )

    SELECT * FROM A, b WHERE A.group_number = b.group_number datum2 datum1

    )

    CBC ON (drc.billing_id = src.billing_id)

    WHEN MATCHED THEN

    UPDATE SET drc.maximum_age = src.max_age - 1

    Error in the command line: 50 column: 1

    Error report:

    SQL error: ORA-00918: column ambiguously defined

    00918 00000 - "ambiguously defined column.

    * Cause:

    * Action:

    Thanks in advance

    Concerning

    Shu

    WITH datum1 AS (SELECT A.group_number,

    b.billing_id,

    b.rate,

    b.maximum_age,

    b.package_id

    OF group_mst A, b billing

    WHERE A.package_id = b.package_id),

    datum2 AS (SELECT max_age, group_number FROM age_max)

    SELECT A.*, b.max_age, b.group_number as group_number_b - ERROR HERE

    OF datum1 A, b datum2

    WHERE A.group_number = b.group_number

  • MERGE statement is increment the sequence. It problem?


    Hi all

    I use a merge statement to update thousands of data in a table. If the criteria does not match (WHEN NOT MATCHED) I wrote an insert statement that contains a reference to the sequence. And it works very well.

    My question is, will this increment also sequence even though it won't insert the statement in the script of fusion. I think it will be. Right?

    Say, I update 20K record will be the sequence also increment by 20 times k. If his past all work around.

    Thanks in advance.

    Here is a less effective solution to your problem that creates a function to get the value of the following sequence, but I agree with Justin cave that because of the cache you must lose the values.

    SQL > CREATE SEQUENCE s_emp;

    Order of creation.

    SQL > CREATE or REPLACE FUNCTION s_emp_nextval

    2 RETURN NUMBER

    3 AS

    4 v_nextval NUMBER;

    5 BEGIN

    6. SELECT s_emp.nextval

    7 INTO v_nextval

    8 DOUBLE;

    9 v_nextval of RETURN;

    10 END;

    11.

    The function is created.

    SQL > MERGE IN emp t (USING)

    2. SELECT empno, ename

    3 FROM emp) s

    4. WE (t.empno = s.empno)

    5. WHEN MATCHED THEN

    UPDATE 6

    7 SET t.ename = s.ename

    8 WHEN NOT MATCHED THEN

    9 INSERT (empno, ename)

    10 VALUES (s_emp_nextval, 'SMITH');

    14 lines merged.

    SQL > SELECT s_emp. NEXTVAL

    2 FROM dual;

    NEXTVAL

    ----------

    1

  • ORA-30926 - Merge statement

    Hi all

    I am facing a problem of failure to merge because of duplicate statement in the Source table. In a merge statement, what I understand is if the Update statement in which corresponding clause contains WHERE predicates, they are pushed upward to filter the lines of the clause?

    In order to understand, I tried to frame a test case to model how my real scenario is:

    create table tab_src (col1, col2 number number, number of col3, col4 varchar2 (5));
    create table tab_des (col1, col2 number number, number of col3, col4 varchar2 (5));

    insert into tab_src values (1, 1, 1, 'AAA');
    insert into tab_src values (1, 1, 0, "AAB");

    insert into tab_des values (1, 1, -1, null);

    explain plan for
    merge into tab_des d
    a_l'_aide_de)
    Select *.
    of tab_src
    where col3 is not null
    ) s
    on (d.col1 = s.col1
    and d.col2 = s.col2
    )
    When matched then
    update the value of col4 = s.col4
    where d.col3 is not null;

    Select *.
    table (dbms_xplan.display (null, null, 'ALL'));

    Hash value of plan: 3751341164

    --------------------------------------------------------------------------------

    | ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time |

    --------------------------------------------------------------------------------

    |   0 | MERGE STATEMENT |         |     1.    60.     7 (15) | 00:00:01 |

    |   1.  MERGE | TAB_DES |       |       |            |          |

    |   2.   VIEW               |         |       |       |            |          |

    |*  3 |    HASH JOIN |         |     1.    98.     7 (15) | 00:00:01 |

    |   4.     TABLE ACCESS FULL | TAB_DES |     1.    55.     3 (0) | 00:00:01 |

    |*  5 |     TABLE ACCESS FULL | TAB_SRC |     2.    86.     3 (0) | 00:00:01 |

    --------------------------------------------------------------------------------

    Name of the query block / Alias object (identified by the operation identity card):

    -------------------------------------------------------------

    1 MRG$ 1

    3 SALT$ F5BB74E1

    4 SALT$ F5BB74E1 / D@SEL$1

    5. SALT$ F5BB74E1 / TAB_SRC@SEL$2

    Information of predicates (identified by the operation identity card):

    ---------------------------------------------------

    3 - access("D".") COL1 "=" TAB_SRC. " "" COL1 "AND

    "D"." COL2 "=" TAB_SRC. " ("" COL2 ")

    5 - filter ("COL3" IS NOT NULL)

    Projection of the column information (identified by the operation identity card):

    -----------------------------------------------------------

    1 SYSDEF [4], SYSDEF [32720], SYSDEF [1], SYSDEF [76], SYSDEF [32720]

    2 - « D ». "COL3" [NO.22], "S" "." " COL4 ' [VARCHAR2, 5].

    3. (#keys = 2) "D". "COL1" [NO.22], "TAB_SRC" "." " COL1 '[NUMBER, 22],

    "D"." COL2"[NO.22],"TAB_SRC ". ' COL2 '[NUMBER, 22],

    « D ». ROWID [ROWID, 10], "D". "COL4" [VARCHAR2, 5], "D" "." " COL3 '[NUMBER, 22],

    'TAB_SRC '. "COL4" [VARCHAR2, 5], 'COL3 '[NUMBER, 22] "

    4 - « D ». ROWID [ROWID, 10], "D". ' COL1 '[NUMBER, 22],

    "D"." COL2"[NO.22],"D ". "COL3" [NO.22], "D" "." " COL4 ' [VARCHAR2, 5].

    5. "TAB_SRC". "COL1" [NO.22], "TAB_SRC" "." " COL2 '[NUMBER, 22],

    'COL3' [NO.22], "TAB_SRC". "COL4" [VARCHAR2, 5].

    Note

    -----

    -dynamic sampling used for this statement

    The predicate information section made no reference to the column COL3 to the Destination table. Then it would be correct to conclude that the where predicates in the UPDATE clause will play no role in the identification of lines of data from source table/query?

    I use oracle 10.2.0.5.

    That's right, the where clauses are applied as the update is done, they will not be part of the condition WE which identifies the lines merge.  This is why you must make sure that your condition IT only joined the lines to merge and there are no duplicates.

  • Question about the MERGE statement

    Hi all

    I have a small question... I can post code, table creation, etc... but I think this question can be able to be simply answered, if I explain it. If you want me to zip codes, etc... then just ask and I'll do it.

    Here it goes:

    I have a set up merge statement, and I have two columns. One is named ADD_DT, and the other is called LST_UPD_DT.

    Update in the merge statement, the LST_UPD_DT column is updated with the SYSDATE.
    When it is inserted in the merge statement, the ADD_DT column is updated with the SYSDATE.

    So, here is my question:

    Regardless of whether or not the information is updated, the LST_UPD_DT updates the SYSDATE every time. Any advice on how to update the LST_UPD_DT column only if information is changed/updated, so that the information is not changed would be not updated by the SYSDATE? I hope that this question was not too complicated.

    Thank you all and if you want to see the code or examples of table... Please ask and I'll post one. I just thought that this may be able to meet without it.

    Hello

    991769 wrote:
    OK, here's what the table looks like:

    Thank you.

    CREATE TABLE TBL_SUPPLIERS
    (
    SUPP_CD                 VARCHAR2(40 CHAR),
    SUPP_NM                 VARCHAR2(255 CHAR),
    ADD_DT                  VARCHAR2(50 CHAR),
    LST_UPD_DT              VARCHAR2(50 CHAR))
    

    Do not use a VARCHAR2 column for date information. Use a DATE column.

    CREATE TABLE D_SUPPLIERS
    (
    SUPP_CD                 VARCHAR2(40 CHAR),
    SUPP_NM                 VARCHAR2(255 CHAR))
    
    INSERT INTO TBL_SUPPLIERS VALUES (1234, MINING, '03-26-2013 3:33:49 PM', '04-02-2013 9:04:52 AM');
    INSERT INTO TBL_SUPPLIERS VALUES (2345, ELECTRIC, '03-26-2013 3:33:49 PM', '04-02-2013 9:04:52 AM');
    INSERT INTO TBL_SUPPLIERS VALUES (3456, COAL, '03-26-2013 3:33:49 PM', '04-02-2013 9:04:52 AM');
    

    You want people to view the solutions that actually work? Please make sure that your own instructions will actually work. Test and fix your code before posting.
    All INSERT statements you posted fail; You seem to be missing single quotes around string literals. I think you meant:

    INSERT INTO TBL_SUPPLIERS VALUES (1234, 'MINING', '03-26-2013 3:33:49 PM', '04-02-2013 9:04:52 AM');
    ...
    

    Here's one way:

    MERGE INTO  tbl_suppliers     sm
    USING  (
               SELECT  d.*
            FROM              d_suppliers        d
            LEFT OUTER JOIN  tbl_suppliers  t  ON  t.supp_cd  = d.supp_cd
            WHERE   t.supp_cd                            IS NULL
            OR        DECODE (t.supp_nm, d.supp_nm, 0, 1) = 1
           )                       ds
    ON     (sm.supp_cd = ds.supp_cd)
        WHEN MATCHED THEN
            UPDATE SET
                sm.supp_nm = ds.supp_nm,
                sm.lst_upd_dt = SYSDATE
        WHEN NOT MATCHED THEN
            INSERT (sm.supp_cd, sm.supp_nm, sm.add_dt)
            VALUES
            (ds.supp_cd, ds.supp_nm, SYSDATE);
    
    SELECT     *
    FROM     tbl_suppliers
    ORDER BY     SUPP_CD;
    

    This can be more efficient, because it does not generate redo, or triggers, when two tables have exactly the same line.

  • Merge statement: update only when a difference

    Hello

    I have two tables have almost the same columns, how can I use the merge statement to update the table target only when there is difference between the source and target table. Is there an easier way to do not compare every column one by one? I use Oracle 11.2.


    Here's the MERGE statement:

    Merge into trgt tb_trgt using tb_src src
    on (src.id = trgt.id)
    When not matched then values of insertion (trgt.id, trgt.nm, trgt.addr) (src.id, src.nm, src.nm)
    when matched, then update set trgt.nm = src.nm, trgt.addr = src.addr
    where trgt.nm <>src.nm or trgt.addr <>src.addr
    ;

    Is there an easier way to clarify the clause in the NO MATCHED? I don't want to compare every column in the tables. Because I might have a lot of columns in tables.

    Thank you

    939569 wrote:
    I have two tables have almost the same columns, how can I use the merge statement to update the table target only when there is difference between the source and target table. Is there an easier way to do not compare every column one by one? I use Oracle 11.2.
    Is there an easier way to clarify the clause in the NO MATCHED? I don't want to compare every column in the tables. Because I might have a lot of columns in tables.

    I use the method of Tom Kyte to compare tables; It gives me the differences between the source and the target using GROUP BY, who manages the value NULL comparisons. Can I use this result in the MERGER. Here is a step by step illustration. First, set up test data:

    define num_rows = 10
    /
    define pct = 20
    /
    define value_length = 50
    /
    define num_mods = round((&num_rows/3)*(&pct/100),0)
    /
    DROP TABLE T_TARGET;
    /
    DROP TABLE T_SOURCE;
    /
    create table t_target(key1 number, value1 varchar2(&value_length), constraint pk_target primary key(key1));
    insert /*+ append */ into t_target
    select level+&num_mods*3, rpad('DO NOTHING - same in source and target ',&value_length, '*')
    from dual
    where level <= &num_rows-&num_mods*2 connect by level <= &num_rows-&num_mods*2;
    /
    create table t_source as select * from t_target;
    /
    insert into t_source
    select level, rpad('INSERT - in source, not in target ',&value_length, '*')
    from dual where level <= &num_mods connect by level <= &num_mods;
    /
    insert into t_target
    select level+&num_mods, rpad('DELETE (after update) - not in source, in target ',&value_length, '*')
    from dual where level <= &num_mods connect by level <= &num_mods;
    /
    insert into t_source
    select level+&num_mods*2, rpad('UPDATE - put this in target ',&value_length, '*')
    from dual where level <= &num_mods connect by level <= &num_mods;
    /
    insert into t_target
    select level+&num_mods*2, rpad('UPDATE - update this from source ',&value_length, '*')
    from dual where level <= &num_mods connect by level <= &num_mods;
    /
    commit;
    /
    select 't_target', count(*), value1 from t_target group by 't_target', value1
    union all
    select 't_source', count(*), value1 from t_source group by 't_source', value1;
    /
    'T_TARGET'   COUNT(*) VALUE1
    ---------- ---------- --------------------------------------------------
    t_target            1 UPDATE - update this from source *****************
    t_target            8 DO NOTHING - same in source and target ***********
    t_target            1 DELETE (after update) - not in source, in target *
    t_source            1 UPDATE - put this in target **********************
    t_source            8 DO NOTHING - same in source and target ***********
    t_source            1 INSERT - in source, not in target ****************
    

    So, I need to do an insert, update, and a delete.

    Now I'll build code comparison step by step. I don't show the results every time, but if you run each query yourself can see what is happening.

    -- Step by step build of "refresh by merge" USING ROWIDs
    -- Result: with cardinality hint, can use "BY USER ROWID" and avoid 3d full scan
    -- 1) Full scan of both tables to get data,
    -- identify old / new records and get old ROWID
    select KEY1,VALUE1,
    1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
    UNION ALL
    SELECT KEY1,VALUE1,
    0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
    /
    -- 2) GROUP BY compares records, identical records have old_cnt = new_cnt
    select KEY1,VALUE1,
    sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
    FROM (
      select KEY1,VALUE1,
      1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
      UNION ALL
      SELECT KEY1,VALUE1,
      0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
    )
    group by KEY1,VALUE1
    /
    -- 3) Filter out identical records
    select KEY1,VALUE1,
    sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
    FROM (
      select KEY1,VALUE1,
      1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
      UNION ALL
      SELECT KEY1,VALUE1,
      0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
    )
    group by KEY1,VALUE1
    having sum(old_cnt) <> sum(new_cnt)
    /
    -- 4) for INSERT, keep NEW; for DELETE, keep OLD;
    -- for UPDATE, keep NEW values and OLD rid
    SELECT /*+ cardinality(1) */ KEY1,VALUE1,
    old_cnt, new_cnt, row_number() OVER(PARTITION BY KEY1 ORDER BY old_cnt) rn
    , max(rid) over(partition by key1) rid
    from (
      select KEY1,VALUE1,
      sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
      FROM (
        select KEY1,VALUE1,
        1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
        UNION ALL
        SELECT KEY1,VALUE1,
        0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
      )
      group by KEY1,VALUE1
      having sum(old_cnt) <> sum(new_cnt)
    )
    /
    -- 5) Filter out OLD UPDATE record, not needed
    SELECT KEY1,VALUE1,
    new_cnt, rid
    FROM (
      SELECT /*+ cardinality(1) */ KEY1,VALUE1,
      old_cnt, new_cnt, row_number() OVER(PARTITION BY KEY1 ORDER BY old_cnt) rn
      , max(rid) over(partition by key1) rid
      from (
        select KEY1,VALUE1,
        sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
        FROM (
          select KEY1,VALUE1,
          1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
          UNION ALL
          SELECT KEY1,VALUE1,
          0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
        )
        group by KEY1,VALUE1
        having sum(old_cnt) <> sum(new_cnt)
      )
    ) where rn = 1
    /
    
    KEY1     VALUE1                                   NEW_CNT     RID
    1     INSERT - in source, not in target ****************     1
    2     DELETE (after update) - not in source, in target *     0     AAAcDHAAMAAAACtAAA
    3     UPDATE - put this in target **********************     1     AAAcDHAAMAAAACtAAB
    

    Now, here's the real MERGER:

    merge into T_TARGET o
    USING (
      SELECT KEY1,VALUE1,
      new_cnt, rid
      FROM (
        SELECT /*+ cardinality(1) */ KEY1,VALUE1,
        old_cnt, new_cnt, row_number() OVER(PARTITION BY KEY1 ORDER BY old_cnt) rn
        , max(rid) over(partition by key1) rid
        from (
          select KEY1,VALUE1,
          sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
          FROM (
            select KEY1,VALUE1,
            1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
            UNION ALL
            SELECT KEY1,VALUE1,
            0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
          )
          group by KEY1,VALUE1
          having sum(old_cnt) <> sum(new_cnt)
        )
      ) where rn = 1
    ) n
    on (o.rowid = n.rid)
    when matched then update set
    VALUE1=n.VALUE1
    DELETE WHERE (n.new_cnt = 0)
    WHEN NOT MATCHED THEN INSERT (
      KEY1,VALUE1
    ) VALUES (
      n.KEY1,n.VALUE1
    )
    /
    

    Published by: stew Ashton on February 7, 2013 20:42

  • understanding "delete all entries" and options such as ' front ' SYSDATE-1 ".

    Hello.

    I'm under Oracle 11.2 on Solaris 10.

    My question is with the archivelogs backup options.
    My goal here is to let the archivelogs that have been backed up nightly on the server for 24 hours extra after their backup. (The reason is for our database of backup in case I have to restore it and have the handy archivelogs without restoring them.)

    My statement of current backup for archiving logs is:
    backup
     tag='archivelogs'
     archivelog all
     delete all input
     format '$DESTDIR/%T_%d_ARCH_%s_%p.af';
    I've considered adding * front ' SYSDATE-1' in the above statement as follows:
     delete all input before 'SYSDATE-1'
    This would keep the archivelogs on the server for an extra day?
    And it would remove the archive automatically that are older than one day?

    I also have the following lines after the execution of my main media:
    run {
    crosscheck backup;
    crosscheck copy;
    delete noprompt expired backup;
    crosscheck archivelog all;
    delete noprompt archivelog all completed before 'SYSDATE-1';   <==========
    #delete noprompt force obsolete DEVICE TYPE disk;
    }

    Hello;

    INPUT DELETE command deletes the archived log files after that that they are saved.

    REMOVE all THE ENTRIES, RMAN deletes every file saved newspaper archived redo log archiving destinations. Alone option
    only in archived redo logs.

    Then you may want something like that

    BACKUP ARCHIVELOG ALL ENTRIES TO DELETE UNTIL ' SYSDATE - 2';

    I'm not a fan of the ENTRY to REMOVE myself.

    I use:

    delete noprompt ARCHIVELOG until TIME ' SYSDATE-2;

    Best regards

    mseberg

Maybe you are looking for