Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Sunny.

Asked: May 02, 2019 - 10:22 am UTC

Last updated: May 09, 2019 - 9:47 am UTC

Version: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production

Viewed 1000+ times

You Asked

Hi Tom ,
I have a trigger script which needs to be executed for a table whose columns keep on changing as per the plugin changes . Once we have assumed that we have new columns into our table () , I need to develop a trigger which captures the DML operation on this table which has alert columns in it . I have written following trigger script which has been compiled successfully but does not insert any entry into CDC (Change data capture table) :-

CREATE OR REPLACE TRIGGER TCDC_TG_Table1
BEFORE    
INSERT ON Table1  
REFERENCING            
OLD AS old    NEW AS new    
FOR EACH ROW
DECLARE
    old_col_value   VARCHAR2(4000) default null;
    new_col_value   VARCHAR2(4000) default null;
    t_type          VARCHAR(1);
    t_dcid          NUMBER(10, 0);
    t_alertname     VARCHAR(30);
    lv_query        VARCHAR(500);
    lv_col          VARCHAR(50);
PRAGMA AUTONOMOUS_TRANSACTION; 
BEGIN
    t_type := NULL;
    FOR rec IN (SELECT t.column_name FROM all_tab_cols t WHERE t.table_name = 'TABLE1' AND t.column_name LIKE '%IS%') LOOP
        lv_col := rec.column_name;
        lv_query := 'select :old.'|| lv_col || ', :new.'|| lv_col|| ' from dual';
  
  
        EXECUTE IMMEDIATE lv_query INTO old_col_value,new_col_value;
  T_ALERTNAME := REC.COLUMN_NAME;
  --old_col_value := :old.lv_col;
  --new_col_value := :new.lv_col;
        IF inserting AND new_col_value = 1 THEN
            t_type := 'I';
            t_dcid := :new.studentsdcid;
   
        END IF;
        IF updating THEN
            IF old_col_value = 1 AND nvl(new_col_value, 0) = 0 THEN
                t_type := 'D';
            ELSE
                IF nvl(old_col_value, 0) = 0 AND new_col_value = 1 THEN
                    t_type := 'U';
                END IF;
            END IF;
            t_dcid := :new.studentsdcid;
        END IF;
        IF deleting THEN
            t_type := 'D';
            t_dcid := :old.studentsdcid;
        END IF;
        IF t_type IS NOT NULL THEN
            INSERT INTO CDC (
                talend_cdc_subscribers_name,
                talend_cdc_state,
                talend_cdc_type,
                talend_cdc_creation_date,
                dcid,
                alertname
            ) VALUES (
                'STUDENTSALERTSUB',
                '0',
                t_type,
                systimestamp,
                t_dcid,
                t_alertname
            );
 commit;  
        END IF;
    END LOOP;
EXCEPTION
    WHEN OTHERS THEN
        NULL;
END;


Could you please help me here as to what I am doing wrong here ?

and Connor said...

I think this is a bad idea to tackle the problem this way. It will be incredibly inefficient to run.

Perhaps a better idea would be to have a database level trigger that is fired when you make a DDL change to the table, and this then dynamically re-generates the *trigger* , so that the trigger has static code not dynamic code.

I think that will be a better approach than this one.

Is this answer out of date? If it is, please let us know via a Comment

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library