Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

get columns name and value dynamically from trigger

Yann39Jul 9 2013 — edited Jul 18 2013

Hi,

Oracle 11g r2.

I know the topic title is not very clear let me give more details.

I have to audit some table to log all modifications (inserts, updates, deletes).

I wrote the following trigger (works as expected) :

-- Trigger for DOCUMENT table audit
CREATE OR REPLACE TRIGGER TAUDIT_IUD_DOCUMENT
AFTER INSERT OR UPDATE OR DELETE ON DOCUMENT
FOR EACH ROW
DECLARE
    l_user VARCHAR2(64);
    l_date DATE;
    l_row CLOB;
    l_separator varchar2(3) := ' | ';

    l_action varchar2(16);
BEGIN
    -- get user
    l_user := nvl(v('APP_USER'), USER);

    -- get date
    SELECT sysdate INTO l_date FROM dual;

    -- if inserting, record new values
    IF INSERTING THEN

        l_action := 'INSERT';
        l_row :=     'DOCUMENT_ID=' || :NEW.DOCUMENT_ID || l_separator ||
                'ARCHIVE_ID=' || :NEW.ARCHIVE_ID || l_separator ||
                'SERVICE_ID=' || :NEW.SERVICE_ID || l_separator ||
                'DOCUMENT_TYPE_ID=' || :NEW.DOCUMENT_TYPE_ID || l_separator ||
                'STORAGE_MEDIUM_ID=' || :NEW.STORAGE_MEDIUM_ID || l_separator ||
                'DOCUMENT_STATUS_ID=' || :NEW.DOCUMENT_STATUS_ID || l_separator ||
                'LOCATION_ID=' || :NEW.LOCATION_ID || l_separator ||
                'REQUEST_ID=' || :NEW.REQUEST_ID || l_separator ||
                'DOC_NAME=' || :NEW.DOC_NAME || l_separator ||
                'URL=' || :NEW.URL || l_separator ||
                'IS_CONFIDENTIAL=' || :NEW.IS_CONFIDENTIAL || l_separator ||
                'DOC_CODE=' || :NEW.DOC_CODE || l_separator ||
                'DOC_VER=' || :NEW.DOC_VER || l_separator ||
                'DESTRUCTION_DT=' || :NEW.DESTRUCTION_DT || l_separator ||
                'CREATION_DT=' || :NEW.CREATION_DT || l_separator ||
                'COMMENTS=' || :NEW.COMMENTS || l_separator ||
                'AUTHOR=' || :NEW.AUTHOR || l_separator ||
                'ROOM_NAME=' || :NEW.ROOM_NAME;

    -- if updating then record only changed values
    ELSIF UPDATING THEN

        l_action := 'UPDATE';

        [...]

    -- if deleting, record old values
    ELSIF DELETING THEN

        l_action := 'DELETE';

        [...]

    ELSE

                NULL;

    END IF;

    -- insert values
    IF l_row IS NOT NULL THEN
        INSERT INTO AUDIT_TABLE (DA_ID, DA_USER, DA_DATE, DA_ACTION, DA_TABLE, DA_ROW)
        VALUES (S_AUDIT_TABLE.NEXTVAL, l_user, l_date, l_action, 'DOCUMENT', l_row);
    END ID;

END;

Is there any way I can improve this ?

I mean getting columns name and value (:NEW and :OLD) dynamically, instead of specifying them one by one (the trigger will have to be updated in case a new column is added).

Something like this :

FOR i in 1..DOCUMENT.COLUMN_COUNT LOOP

    l_row := l_row || DOCUMENT.COLUMN_NAME(i) || :NEW.COLUMN_VALUE(i) || l_separator;

END LOOP;

Any idea ?

Thanks.

Yann.

Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Aug 15 2013
Added on Jul 9 2013
6 comments
5,007 views