Trigger compiled successfully but still not firing as desired - plsql

Here is my simple PL/SQL code for demonstration purpose.
create table cust(cname varchar(10));
set SERVEROUTPUT ON;
create or replace trigger tgr
before insert on cust
for each row
enable
begin
dbms_output.put_line('Trigger hit on insert');
end;
/
insert into cust values('John');
OUTPUT:/
Table CUST created
Trigger TGR compiled
1 row inserted // *EXPECTING* Trigger hit on insert

You can't use DBMS_OUTPUT.PUT_LINE because when you insert data to your table, there is no prompt or screen which shows the execution of trigger. this applied same for procedures , functions , triggers.
Don't use commit inside a table. it will throw an exception. if you want to use commit then make the trigger pragma autonomous_transaction (i suggest not to use commit.it will automatically commit) .
Also make sure you don't modify the same table in the trigger. it will also throw and exception for mutating the data.
sample code
create table cust(cname varchar(10));
create table log(log varchar(10));
create or replace trigger tgr
before insert on cust
for each row
enable
begin
insert into log values('test');
end;
/

Don't use DBMS_OUTPUT.PUT_LINE inside a trigger to check if it was fired or not. Some of the IDEs like SQL developer might not output the message , even if you use SET SERVEROUTPUT ON.
However it could work on sqlplus . When i tried, it did display the message in sqlplus. So, it is not an issue with the database or your trigger.
SQL> insert into cust values('John');
Trigger hit on insert
And if you issue commit or rollback on the transaction, the messages might appear in sql developer.
I would suggest , it is better if you can create a log table and try to insert records into it rather than use dbms_output.
begin
INSERT INTO LOG_TABLE ( log_date,log_message) VALUES (SYSDATE,'Trigger hit on insert');
end;
/

Related

sqlite3 got syntax error while executing vacuum in a trigger

I'm using sqlte3.8.8, trying to create a trigger to clean old data. Here is the SQL that I put in:
CREATE TRIGGER "main"."NewTrigger" AFTER INSERT ON "historydata"
BEGIN
delete from historydata where id in (select id from historydata order by id limit 100000);
vacuum;
END;
But I got Syntax error on "vacuum;".However, it works fine in sqlite command line.
Is it the case that "vacuum" cannot be used in a trigger?
The documentation shows that only UPDATE/INSERT/DELETE/SELECT statements are allowed in a trigger body.

SQLite - Create Trigger for Insert or Update

Is this possible to create one trigger for Insert and Update operations in SQLite?
I mean, something like this:
CREATE TRIGGER dbo.TR_TableName_TriggerName
ON dbo.TableName
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS(SELECT * FROM INSERTED)
-- DELETE
PRINT 'DELETE';
ELSE
BEGIN
IF NOT EXISTS(SELECT * FROM DELETED)
-- INSERT
PRINT 'INSERT';
ELSE
-- UPDATE
PRINT 'UPDATE';
END
END;
It's for MS SQL i think, source: Insert Update trigger how to determine if insert or update
Edit:
Is it possible to create also one trigger for more than one table?
No, the syntax graph for CREATE TRIGGER clearly shows that only one of INSERT, UPDATE or DELETE can be given.
It also shows that only one table can be given as a table to trigger on.

How to fix the mutating trigger in oracle

I wrote the trigger for updating the column value in the same table. For Ex I wrote a trigger on metermaster table after update of assettype column , with in the trigger i am trying to update the instantaneousinterval column in the same metermaster table. Its throws the error like this
ERROR: ORA-04091: table PSEB.METERMASTER is mutating, trigger/function
may not see it.
my trigger code is as follows:
CREATE OR REPLACE TRIGGER PSEB.spiupdate
AFTER
update of assettype
ON pseb.metermaster
referencing new as new old as old
for each row
DECLARE
vassettype number;
resval number(10);
vassettypename varchar2(50);
vmeterid number;
begin
select :new.assettype,:new.meterid INTO vassettype,vmeterid from dual;
select assettypename into vassettypename from pseb.METERASSETINSTTYPE where ASSETTYPEID=vassettype;
select case when assettypename like 'DT' then 86400 when assettypename like 'HT' then 3600 when assettypename like 'FSB' then 86400 end into resval from pseb.meterassetinsttype where assettypename =vassettypename;
update pseb.metermaster set instantaneousinterval=resval where meterid=vmeterid;
end;
I tried to use the
pragma autonomous_transaction;
but it gives the deadlock condition.
ERROR: ORA-00060: deadlock detected while waiting for resource
ORA-06512:
pls help me to fix this issue.
instead of this update statement
update pseb.metermaster set instantaneousinterval=resval where meterid=vmeterid;
use
:new.instantaneousinterval=resval;
A mutating table occurs when a statement causes a trigger to fire and that trigger references the table that caused the trigger. The best way to avoid such problems is to not use triggers, but I suspect the DBA didn’t take the time to do that. He could have done one of the following:
Changed the trigger to an after trigger.
Changed it from a row level trigger to a statement level trigger.
Convert to a Compound Trigger.
Modified the structure of the triggers to use a combination of row and statement level triggers.
Made the trigger autonomous with a commit in it.
Try this pragma autonomous_transaction; with Commit
Since the trigger is updating the same table on which it is defined, why don't you update the two columns in the first update statement itself?
i.e, Instead of using an update like
UPDATE pseb.metermaster
SET assettype = '<v_assettype>';
and relying on trigger to update the instantaneousinterval column, why don't you use an update statement like the following (code is not tested)
UPDATE pseb.metermaster
SET assettype = '<v_assettype>',
instantaneousinterval = (SELECT CASE
WHEN assettypename LIKE 'DT' THEN 86400
WHEN assettypename LIKE 'HT' THEN 3600
WHEN assettypename LIKE 'FSB' THEN 86400
END
FROM pseb.meterassetinsttype
WHERE assettypeid = '<v_assettype>');
In my opinion, using a trigger and autonomous_transaction in this case would be a wrong approach. To know why this is wrong, please search http://asktom.oracle.com/ for this error.

INSERT inside plsql procedure does not tell how many rows were inserted

i am trying to insert some rows and update some rows inside a pl/sql loop.
however all i get to see is the pl/sql procedure is successfully completed.
i do get to see dbmbs_ouput statements but not the output status of insert and/or update queries.
the serveroutput is set to on.
how do i get to see the status of insert and update rows(namely how many rows were inserted and updated)
In Oracle, the rowcount is not output automatically like it is in SQL Server.
You should do it explicitly:
BEGIN
INSERT
INTO mytable
SELECT …
FROM other_table;
DBMS_OUTPUT.put_line(SQL%ROWCOUNT);
END;

sqlite UPDATE trigger firing on INSERT statements also?

I'm working on setting up a simple SQLite database to access via Python. So far I have one basic table, and a couple of triggers - I want to have one trigger update a field column 'date_added' when a new record is added, and another one to update a column 'date_updated' when a record is later updated. Here is my SQLite syntax for the triggers:
CREATE TRIGGER add_contact AFTER INSERT ON contact_info
BEGIN
UPDATE contact_info SET date_added = DATETIME('NOW') WHERE pkid = new.pkid;
END;
CREATE TRIGGER update_contact AFTER UPDATE ON contact_info
BEGIN
UPDATE contact_info SET date_updated = DATETIME('NOW') WHERE pkid = new.pkid;
END;
The 'add_contact' trigger seems to be working fine... it fires when I add a new record via an sql INSERT command, as planned.
The problem seems to be the 'update_contact' trigger... it fires both when I update a record via an sql UPDATE command (as planned) and when I add a new record also:
i.e. when I add a new record I get this in the 'date_added' and 'date_updated' columns:
2010-07-12 05:00:06|2010-07-12 05:00:06
and when I update that record, it changes like so:
2010-07-12 05:00:06|2010-07-12 05:14:26
I guess I'm not getting why the UPDATE trigger fires on INSERT also?
TIA,
Monte
Edited to add: Any hints on how to make it work as intended?
A better way to avoid the original problem is to use a DEFAULT ( DATETIME('NOW') )
clause for the date_added column in the table definition, instead of using an INSERT trigger.
You have an UPDATE in your INSERT trigger. So the INSERT causes an UPDATE. Which you have hooked with a different trigger.

Resources