I am looking for a way to know all the events occurred on a specific table without enabling postgres logs.
Just want to know weather the sequence of addition/deletion/ Modification.
Thanks
For audit trail in postgres you have to write an function and call it in a trigger, please have a look at wiki.postgresql.org/wiki/Audit_trigger , You will have to write a function stating that if an update or delete or insert is happening on a table it will trigger an action updating a audit table capturing required information such as ip address, query, old data, new data, timestamp of the action that has occured etc..
You can create triggers (see postgres docs) to observe all changes, e.g.:
CREATE TRIGGER insert_trigger AFTER INSERT ON my_table
EXECUTE PROCEDURE insert_function();
CREATE TRIGGER update_trigger AFTER UPDATE ON my_table
EXECUTE PROCEDURE update_function();
CREATE TRIGGER delete_trigger AFTER DELETE ON my_table
EXECUTE PROCEDURE delete_function();
or do this with just one function:
CREATE TRIGGER universal_trigger AFTER INSERT OR UPDATE OR DELETE ON my_table
EXECUTE PROCEDURE universal_function();
Related
How do I get the performed operation and affected table from a database trigger in oracle?
I want to create a trigger for a schema in Oracle which gets executed on drop or alter or create on database So I need something similar like inserting, updating, deleting but for DDL statements, and somehow I need to know the affected table and schema.
The documentation has a list of the event attribute functions that you can access. It looks like you'd want ora_sysevent for the event along with ora_dict_obj_name and ora_dict_obj_owner to identify the object in question.
The problem here is that, we use an application called ArcGIS that creates an upper management layer for our database, and when our users use ArcGIS to create a new object in the database, it adds a default value (0) to the primary key, so when the second object is created it triggers an ORA error for having duplicate values.
So my idea was to create an auto increment trigger for our PK but use AFTER INSERT instead.
I couldn't find any example online for this specific case and simply switching BEFORE to AFTER gives an error saying that you can't use NEW with AFTER
SQL code of what I tried (taken from other questions):
CREATE OR REPLACE TRIGGER "IMOVEL_TRIGGER"
after insert on IMOVEL
for each row
begin
select IMOVEL_SEQ.nextval into :NEW.GEOCODIGO_IMOVEL from dual;
end;
It cant be a BEFORE INSERT trigger, because the application overwrites it
Simplifying, what I need is a AFTER INSERT trigger, that updates the PK to the sequence .nextval, it doesn't let me use :OLD or :NEW, so I'm not sure what must be done.
Or an update trigger that only runs after it is created
This is pretty new territory for me, having to learn SQL now just to solve this issue
You can change :NEW values only in a BEFORE trigger. By the time you reach the AFTER trigger, the row has already been inserted, so it's too late to change the columns.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7004.htm says:
Restrictions on BEFORE Triggers
BEFORE triggers are subject to the following restrictions:
You cannot specify a BEFORE trigger on a view or an object view.
You can write to the :NEW value but not to the :OLD value.
Restrictions on AFTER Triggers
AFTER triggers are subject to the following restrictions:
You cannot specify an AFTER trigger on a view or an object view.
You cannot write either the :OLD or the :NEW value.
It's not clear why you want to use an AFTER trigger for assigning sequence values to the PK. The common solution is to use a BEFORE trigger.
See example in: How to create id with AUTO_INCREMENT on Oracle?
CREATE SEQUENCE IMOVEL_TRIGGER_SEQ START WITH 1;
Trigger definition:
CREATE OR REPLACE TRIGGER IMOVEL_TRIGGER
BEFORE INSERT ON IMOVEL
FOR EACH ROW
BEGIN
SELECT IMOVEL_TRIGGER_SEQ.NEXTVAL
INTO :new.GEOCODIGO_IMOVEL
FROM dual;
END;
I have a trigger created that will log their username to ChangesLogtbl if they update, delete or insert in TblCurrentRec.
CREATE TRIGGER mytriggerforinsert
#username = username <------------------itried to place something like this
ON TblCurrentRec
AFTER INSERT
AS BEGIN
INSERT INTO ChangesLogtbl
values ('username', 'GETDATE')
END
GO
This works but I want this one to work on all tables within the schema. and also not to limit it on insert but to delete and update as well.
I tried using everything in and over the net and also copied and studied different sample but to no avail. I'm new to SQL and this is my very first time to create a trigger. Hope you guys can understand.
Thanks.
TO cover other DML,
ON TblCurrentRec
AFTER INSERT or UPDATE or DELETE
Coming to schema level coverage, i doubt you can have a single trigger for all tables in schema.Triggers should be written to each table.
If it where DDL we can use DATABASE TRIGGERS
You can use of cursors and the Information_Schema.Tables view to create triggers on all tables of a database.
I want my database to show the table every time while I insert a new row. My code is able to compile but It don't show the table after I insert a new row.
Below is my code :
create trigger show_all
after insert ON Toy
for each row mode db2sql
select * from Toy
This isn't possible.
Triggers don't return a value to the statement (insert) that caused the trigger to fire. Further, that behaviour wouldn't even be possible because multiple triggers could fire in response to an insert, which would get to return something?
You could create a stored procedure that performs an insert and then returns the result of a select, and then call that function instead of inserting directly.
I want to place a trigger on a table which writes all inserted / updated Data to an additional log file for processing with an external tool.
Is the a way to accomplish that?
You need to create triggers that execute after the table row has been altered and write to a log file using the UTL_FILE package.
The UTL_FILE package info can be found here:
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/u_file.htm
And Trigger documentation can be found here:
http://docs.oracle.com/cd/B10501_01/appdev.920/a96590/adg13trg.htm
There is a similar answer to what you are looking for here:
http://bytes.com/topic/oracle/answers/762007-trigger-output-text-file
More info on writing to a file using PL/SQL here:
http://www.devshed.com/c/a/Oracle/Writing-to-Text-Files-in-Oracle-PLSQL/
Hope it helps...
I would avoid writing out to the file system at DML time, but would pull out the data in a batch process each night (or whatever frequency).
From your OP, its not clear if you need the "new" data after the update, or the "old" data before the update. If you just want the latest data, why not just add a modified_date field (date or timestamp type) and update that via a trigger.
create table test
(
id number,
val varchar2(100),
modified_date date default sysdate not null
)
;
CREATE OR REPLACE TRIGGER TR_TEST_BU
BEFORE UPDATE
ON TEST REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
begin
:new.modified_date := sysdate;
end;
insert into test(id, val) values (1, 'Insert 1');
commit;
select * from test;
exec dbms_lock.sleep(5);
update test set val = 'Update 1' where id = 1;
commit;
select * from test;
If you need the old data before the update (or you care about deleted data), then you'll modify the trigger to write old or deleted values to a history table, then extract the data from there.
Also note that adding a trigger to a table will slow down associated DML activity. Some shops wish to avoid this by replacing the triggers with business logic rules ("all apps must update modifed_date" edict), which usually leads to inconsistent data (or worse) from what I've seen.
Yes, here you have an example of the update part.
You simply need to do a similar one to the insert part.