Suggest Event pattern design in database - oracle

Can anyone suggest a good event pattern design or framework for changes in table in oracle.
Changes are not just the based on the column value change,but also the business driven logic .All the logging should be driven by some event setup.
At the end we track the changes and drive the business logic based on the changes .
I might be talking too high level,sorry for that :)

Assume TableA needs to be tracked for ColumnA.
Create AUDIT_TRAIL Table with columns TABLENAME, COLUMNNAME, OLDVALUE,NEWVALUE, DATEANDTIME, PK_SEQ
Create a Trigger to poll TableA for any change in ColumnA, and insert them into AUDIT_TRAIL (PK_SEQ should be a Oracle Sequence Number, DATEANDTIME should be from sysdate)
Something like this for trigger
CREATE OR REPLACE TRIGGER trg_table_audit
before insert or update or delete on tableA REFERENCING NEW AS NEW OLD AS OLD
for each row
begin
if inserting or deleting then
insert into audittrail (....)

Reading the fine manual: Using Triggers to Write Audit Data to a Separate Table:
You can use triggers to supplement the built-in auditing features of Oracle Database. The trigger that you create records user actions to a separate database table. When an activity fires the trigger, the trigger records the action in this table. Triggers are useful when you want to record customized information such as before-and-after changes to a table.
Reading even more the fine manual: PL/SQL Triggers:
A trigger is like a stored procedure that Oracle Database invokes automatically whenever a specified event occurs.
On top of that you can build a setup engine that turns triggers on and off. The "business logic" can later read the data recorded by the triggers.
I assume you're not interested in auditing. For the details see e.g. Verifying Security Access with Auditing.

How about you start with using TRIGGERS? And then from there, you could call procedures/functions from a package body for tracking the changes on the table/s.

Related

What's a way I can save a trigger "template" in oracle?

Let's say I created a table test_table in development just to test a trigger, this trigger would then be reused in many other tables (future and existing).
So I code the trigger, test it, all good! But at the moment, if I want to replicate it, I will have to copy it from test_table's triggers and edit it.
So if someone deletes the table accidentally, the trigger is gone, and I don't have it saved nowhere else. Or if I just want to delete random test tables in our database, I can't.
What's a recommended way to save a trigger as a "template" in oracle? So I can reuse it in other tables and have it not be dependant of a random test table, or any table.
There are a lot of ways you can keep a copy of your TRIGGER SQLText.
Here's a few examples.
In Version Control:
You can use any of the many version control tools to maintain a versioned history for any code you like, including SQL, PL/SQL, etc. You can rewind time, view differences over time, track changes to the template, even allow concurrent development.
As a Function:
If you want the template to live in the database, you can create a FUNCTION (or PACKAGE)that takes as parameters the target USER and TABLE, and it replaces the USER and TABLE values in its template to generate the SQLTEXT required to create or replace the template TRIGGER on the target TABLE. You can make it EDITIONABLE as needed.
In a Table:
You can always just create a TABLE that holds template TRIGGER SQLText as a CLOB or VARCHAR2. It would need to be somewhere where it isn't likele to be "randomly" deleted, though. You can AUDIT changes to the TABLE's data, to see the template change over time. Oracle has tons of auditing options.
In the logs:
You can just log (all) DDL out. If you ENABLE_DDL_LOGGING, the log xml will have a copy of every DDL statement, categorized, along with when and where it came from.

Dynamically read the columns of the :NEW object in an oracle trigger

I have an oracle trigger that needs to copy values from the updated table to another table.
The problem is that the columns aren't known when the trigger is created. Part of this system allows the table schema to be updated by the application. (don't ask).
Essentially what I want to do is pivot the table to another table.
I have a stored procedure that will do the pivot, but I can't call it as part of the trigger because it does a select on the table being updated. Causing a "mutating" error.
What would be ideal would be to create a dynamic scripts that reads all the column names from user_tab_cols for the updated table, and reads the value from the :new object.
But of course...I can't :)
:NEW doesn't exist at the point the dynamic script is executed. So something like the following would fail:
EXECUTE IMMEDIATE `insert into pivotTable values(:NEW.' || variableWithColumnName ||')';
So, I'm stuck.
I can't read from the table that was updated, and I can't read the value that was updated from the :NEW object.
Is there anyway to accomplish this other than rebuilding the trigger each time the schema is changed?
No. You'll need to rebuild the trigger whenever the table changes.
If you want to get really involved, you could write a procedure that dynamically generated the DDL to CREATE OR REPLACE the trigger by reading user_tab_columns. You could then create a DDL trigger that fired when the table was altered, submitted a job via dbms_job that called the procedure to recreate the trigger. That works but it's a rather large number of moving parts which means that it can fail in all sorts of subtle and spectacular ways particularly if the application that is making schema changes on the fly decides to add columns in the middle of the day.

Oracle audit trigger code used for multiple tables with different table names

I have a requirement to populate an audit column with current timestamp only if there are any updates to the table. Here is the trigger. Trigger works fine
create or replace TRIGGER test.Audit_Trigger
BEFORE UPDATE ON test.TEST_TABLE
FOR EACH ROW
BEGIN
:NEW.column_dtm := current_timestamp;
END;
Instead of adding same trigger for every table (around 1000 tables means 1000 triggers) with only change in table name, is there any other better way to accomplish this task?
It would be nice if you could write a schema level trigger to do this, but unfortunately Oracle only supports schema level triggers for DDL, not for DML.
You could generate triggers on each table quite easily using dynamic SQL, but assuming your DB version is reasonably recent (9i or later I think), a better alternative might be to talk to your DBA about turning on fine grained auditing for table updates.
https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_4007.htm

VB6 Audit Trail

was wondering if anyone had any insight on creating an audit trail process in VB6?
I have an application that gets populated with existing data with the use of 3 or 4 classes. The user can then modify any data they wish on this application. Then the data is saved into tables used for a queue. Basically exact copies of the tables the data came from. My problem is I need to create an audit trail.
What is the best practice for this? Compare every control (text box, radio, check box) on the application which is around 100? Or can I utilize the text_changed event of the text boxes? Really have no idea where to start on this one.
Oh and to make it fun, using a Pervasive DB v9.
Thanks for any help.
Cheers
This should always be done inside the DB.
Something like this (cribbed in part from post to the pervasive forum, I haven't actually used Pervasive):
create trigger insTrig
before insert on table1
referencing new as new_rec
for each row
insert into table2 values (new_rec.co1,new_rec.col2,new_rec.col3,...)#
create trigger delTrig
before delete on table1
referencing old as new_rec
for each row
insert into table2 values (new_rec.co1,new_rec.col2,new_rec.col3,...)#
create trigger updTrig
after update on table1
referencing new as new_rec
for each row
insert into table2 values (new_rec.co1,new_rec.col2,new_rec.col3,...)#

How to call the Triggers in user deefined way?

I created the Employee table which contains EmpNo,EName,EDesignation as its fields.Also i created the 3 Triggers namely Trigger_1,Trigger_2 and Trigger_3.All the Triggers are Statement level triggers and fired after the update done in the table.Now i want the following orders in which the triggers are going to fired when the update statement is executed.
The Order is
Trigger_3,
Trigger_1,
Trigger_2
Can anyone tell me the way to fire the trigger events in userdefined way?I m using Oracle 9i
Trigger Evaluation Order
Quote from Oracle documentation:
Although any trigger can run a
sequence of operations either in-line
or by calling procedures, using
multiple triggers of the same type
enhances database administration by
permitting the modular installation of
applications that have triggers on the
same tables.
Oracle Database executes all triggers
of the same type before executing
triggers of a different type. If you
have multiple triggers of the same
type on a single table, then Oracle
Database chooses an arbitrary order to
execute these triggers.
Each subsequent trigger sees the
changes made by the previously fired
triggers. Each trigger can see the old
and new values. The old values are the
original values, and the new values
are the current values, as set by the
most recently fired UPDATE or INSERT
trigger.
To ensure that multiple triggered
actions occur in a specific order, you
must consolidate these actions into a
single trigger (for example, by having
the trigger call a series of
procedures).
see also http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm
Have one trigger with the contents of the three.
If you cannot, for reasons for modularization, reusability..., create three stored procedures and call these one by one in the single trigger.
Upgrade to 11g and you can define trigger execution order

Resources