0

I have a question regarding Oracle cursor.

I need to compare the values in a selected list of columns, see which records have changed after update. The table is huge, the only way to distinguish between new and old record is by the Batch_ID.

The output table will include these information:

enter image description here

So i have something very basic like below, except that i need to write like hundreds of SELECT statement in order to go through hundreds of columns.

SELECT a.*, b.LAST_name AS last_name_updated --- here the variable could be ethnicity, income category etc..
from (SELECT person_id, last_name
      FROM   person  
      WHERE batch_id = (select max(batch_id) from person)
     ) a FULL OUTER JOIN
     (SELECT person_id, last_name
      FROM   person  
      WHERE batch_id = (select max(batch_id) - 1 from person)
     ) b
     ON a.person_id = b.person_id
WHERE  nvl(a.last_name,0) <> nvl(b.last_nm,0)

I need to go through a list of about 500 field name like Income, Race, Last_Name etc and capture all the changes, if any, in all these columns.

how do i go about this without writing hundreds of these SELECT statements?

Thanks in advance for your help!

6
  • here is the base SQL query. SELECT a.*, b.LAST_name AS last_name_updated from (SELECT person_id, last_name FROM person WHERE batch_id = (select max(batch_id) from person) ) a FULL OUTER JOIN (SELECT person_id, last_name FROM person WHERE batch_id = (select max(batch_id) - 1 from person) ) b ON a.person_id = b.person_id WHERE nvl(a.last_name,0) <> nvl(b.last_nm,0) Commented Jul 7, 2017 at 22:01
  • I only work with SQL server, but in Oracle there must be a system table that stores all of this. Look in the master database. You can then query that to get any info about any object in your database. Commented Jul 7, 2017 at 22:03
  • Edit your question and provide sample data and desired results. A cursor is probably not needed for this purpose. Commented Jul 7, 2017 at 22:04
  • @GordonLinoff you're like a StackOverflow god! Good job on all those points. You must have helped many many people. Commented Jul 7, 2017 at 22:05
  • Thanks @MichaelZ... I'm trying to capture all the value change in each column of interest and build a table to store all the before and after value. Commented Jul 7, 2017 at 22:21

1 Answer 1

1

This is a generic SQL statement that will use ALL_TAB_COLS to generate a SQL statement that can be used to compare columns:

  SELECT    CASE WHEN column_id = '1' THEN q'[ select 'batchid: ' || batchid ]' END
         || CASE
                WHEN column_name <> 'BATCHID'
                THEN
                       q'[ || case when ]'
                    || column_name
                    || q'[<> lag(]'
                    || column_name
                    || q'[) over (partition by batchid order by col1, col2) then ' ]'
                    || column_name
                    || ' has changed'' end'
            END
         || CASE WHEN column_id = MAX (column_id) OVER () THEN q'[ as changemessage from testtable]' END
             sql
    FROM all_tab_cols a
   WHERE table_name = 'TESTTABLE'
ORDER BY column_id;

Test Case:

CREATE TABLE testtable
(
    batchid   INTEGER
  , col1      INTEGER
  , col2      INTEGER
);

BEGIN
    FOR batchid IN 1 .. 3
    LOOP
        FOR col1 IN 1 .. 3
        LOOP
            FOR col2 IN 1 .. 2
            LOOP
                INSERT INTO testtable
                     VALUES (batchid, col1, col2);
            END LOOP;
        END LOOP;
    END LOOP;
END;

Execute the SQL and you generate the following SQL statement:

select 'batchid: ' || batchid 
     || case when COL1<> lag(COL1) over (partition by batchid order by col1, col2) then ' COL1 has changed' end
     || case when COL2<> lag(COL2) over (partition by batchid order by col1, col2) then ' COL2 has changed' end as changemessage from testtable

I will leave it to you to reduce the result set:

CHANGEMESSAGE
batchid: 1
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL1 has changed COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL1 has changed COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 1 COL2 has changed
batchid: 1
batchid: 1
batchid: 1
batchid: 2
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL1 has changed COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL1 has changed COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 2 COL2 has changed
batchid: 2
batchid: 2
batchid: 2
batchid: 3
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL1 has changed COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL1 has changed COL2 has changed
batchid: 3
batchid: 3
batchid: 3
batchid: 3 COL2 has changed
batchid: 3
batchid: 3
batchid: 3
Sign up to request clarification or add additional context in comments.

4 Comments

Wow thanks Brian! The code is great example! Thanks much!
Hi @Brian Leach, thanks again! What if I want to display the before and after update value, between the latest and the prior batch? I want the comparison of different values to be stored in an audit trail table, with 4 main columns: batch_id, field_name, current_value, previous_value. In the Field_Name, i will compare about 600 columns such as income, height, address_state, etc... how to make sure that the difference of these information is captured? Thanks again!
@LycorisRadiata You can adjust the generated select statement to perform an insert. I would not store the before/after values, but rather the primary key that would point to the appropriate records. A view could then display before/after values however you want.
Thanks @Brian Leach... yeah, the business requirement is to store the before and after values in an audit table with primary key and distinguishable person_id etc.. The business ask is to have all the changes made to the columns stored in a table...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.