SQL Update Trigger not working as expected - oracle

I have an update trigger on my oracle table..but seems like it's not working..Schema under which triggers and table created is HR
CREATE OR REPLACE Trigger TR_FinlStatAssetDesignation_U
BEFORE update
on FINLSTATASSETDESIGNATION FOR EACH ROW
DECLARE
v_AtDateTime TIMESTAMP(3);
v_LogOperation NUMBER(3,0);
v_UserName VARCHAR2(255);
v_AppName VARCHAR2(255);
SWV_error NUMBER(10,0) DEFAULT 0;
BEGIN
begin
select USERNAME INTO v_UserName FROM v$session WHERE (audsid = SYS_CONTEXT('userenv','sessionid')) AND ROWNUM <=1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
end;
SELECT program INTO v_AppName FROM v$session WHERE audsid=userenv('sessionid');
if (LENGTH(v_AppName) = 0) then
v_AppName := 'Unknown';
end if;
SELECT SYSTIMESTAMP INTO v_AtDateTime FROM dual;
if UPDATING('FinlStatAssetDesignation') then
RAISE_APPLICATION_ERROR(-20000,'Invalid attempt to update OID FinlStatAssetDesignation in FinlStatAssetDesignation');
/*
ROLLBACK */
return;
end if;
if not UPDATING('UpdDate') then
SWV_error := 0;
begin
UPDATE FinlStatAssetDesignation a SET(UpdDate) =(SELECT distinct v_AtDateTime FROM dual where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation)
WHERE ROWID IN(SELECT a.ROWID FROM FinlStatAssetDesignation a where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation);
EXCEPTION
WHEN OTHERS THEN
SWV_error := SQLCODE;
end;
if SWV_error <> 0 then
/*
ROLLBACK */
return;
In this trigger.. second part i.e below is not working of trigger..please help....it is not updating the timestamp in upddate column
SQL> select * from finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 anyt 0
hinh
01-JAN-17 08.00.00.000000 AM
SQL> update finlstatassetdesignation set finlstatassetdesignationdesc ='nothing';
1 row updated.
SQL> select * From finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 nothing 0
01-JAN-17 08.00.00.000000 AM

What are you trying to accomplish in the ON INSERT trigger? From your comment of
I still can insert a row as user "hello"..hence trigger is not working..
you seem to want to prevent a user named HELLO from being added - but in your trigger code if a username of HELLO is found you simply return from the trigger. That doesn't accomplish anything. To signal to the system that you don't want the INSERT to proceed you must raise an exception in your trigger. For example:
CREATE OR REPLACE Trigger TR_FinlStatAssetDesignation_I
BEFORE Insert on FINLSTATASSETDESIGNATION
BEGIN
if USER = 'HELLO' or USER = 'SYSTEM' then
RAISE_APPLICATION_ERROR(-20000, 'Invalid user in TR_FinlStatAssetDesignation_I');
end if;
END TR_FinlStatAssetDesignation_I;
Raising an exception in this manner will prevent the INSERT from proceeding to successful completion. Your code is responsible for providing an appropriate error handler.
Best of luck.

Related

PL/SQL exception handling - log errors

How do I record the oracle error in a pl/sql script? I have been to the oracle error handling documentation and I see the built in exceptions, but what if I do not know what the exception is? How can I log this in an exception block?
I want to do something like the below.
exception
when others then DBMS_OUTPUT.PUT_LINE(the error)
It's easier to create error logging database trigger with conditional logging, for example my actual error_logging trigger: https://github.com/xtender/xt_scripts/blob/master/error_logging/on_database.sql
create table ERROR_LOG
(
id NUMBER,
username VARCHAR2(30),
errcode INTEGER,
seq INTEGER,
tmstmp TIMESTAMP(6),
msg VARCHAR2(4000),
sql_text CLOB
)
/
create sequence err_seq
/
create or replace trigger trg_error_logging
after servererror
on database
disable
declare
v_id number := err_seq.nextval();
v_tmstmp timestamp:= systimestamp;
n int;
sql_text dbms_standard.ora_name_list_t;
v_sql_text clob;
begin
-- only if plsql_debug is set to TRUE:
for r in (select * from v$parameter p where p.name='plsql_debug' and upper(p.value)='TRUE') loop
v_sql_text:=null;
n := ora_sql_txt(sql_text);
for i in 1..n loop
v_sql_text := v_sql_text || sql_text(i);
end loop;
for i in 1.. ora_server_error_depth
loop
if i=1 then
insert into error_log(id,seq,tmstmp,username,errcode,msg,sql_text)
values( v_id, i, v_tmstmp, user, ora_server_error(i), ora_server_error_msg(i), v_sql_text);
else
insert into error_log(id,seq,tmstmp,username,errcode,msg)
values( v_id, i, v_tmstmp, user, ora_server_error(i), ora_server_error_msg(i) );
end if;
end loop;
commit;
end loop;
END;
/
select object_name,object_type,status from user_objects o where object_name='TRG_ERROR_LOGGING'
/
alter trigger trg_error_logging enable
/
As you can see it logs all errors into the table ERROR_LOG, but only if session parameter plsql_debug is set to true. Obviously, you can change it to own parameters or conditions.

WHEN-BUTTON-PRESSED trigger raise unhendled exception ORA-01407

I am new in PL SQL and I am trying to resolve problem with copy-past data from .CVS file to database
I create a small application which will take data from .CVS and past it to database.
I create a method, but after I compile it's writtend Successfully compiled
But when I run form I get error
WHEN-BUTTON-PRESSED trigger raise unhendled exception ORA-01407
Does anyone know what this means since I google it and could not find anything ?
I would be very thankfull
declare
import_file text_io.file_type;
import_file_name varchar2(1000);
import_log_file text_io.file_type;
import_log_file_name varchar2(1000);
vec_importovano number;
brojac number;
brojac_redova number;
linebuf varchar2(5000);
p_rbr varchar2(4);
p_polica varchar2(20);
p_banka varchar2 (20);
p_kontakt varchar2(20);
kraj_fajla number;
begin
import_file_name := :Global.Lokacija_prenosa||:import.naziv_fajla||:Global.Ekstenzija_prenosa;
import_file := text_io.fopen(import_file_name,'r');
--p_rbr := 100000;
delete from zivot_trajni_nalog_ponude where banka is not null;
commit;
kraj_fajla := 0;
while kraj_fajla = 0 loop
begin
text_io.get_line(import_file, linebuf);
if brojac_redova>=2 then
if length(linebuf)>100 then
p_rbr:=substr(linebuf, 1, instr(linebuf,';',1,1)-1);
p_polica:=substr(linebuf, instr(linebuf,';',1,1)+1, instr(linebuf,';',1,2) - instr(linebuf,';',1,1)-1);
p_banka:=substr(linebuf, instr(linebuf,';',1,2)+1, instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
p_kontakt:=substr(linebuf, instr(linebuf,';',1,3)+1, instr(linebuf,';',1,4) - instr(linebuf,';',1,3)-1);
select count(*)
into vec_importovano
from ZIVOT_TRAJNI_NALOG_PONUDE
where broj_police=p_polica and p_rbr=redni_broj;
if vec_importovano=0 then
insert into ZIVOT_TRAJNI_NALOG_PONUDE values(p_rbr, p_polica, p_banka, p_kontakt);
commit;
end if;
end if;
end if;
EXCEPTION WHEN NO_DATA_FOUND THEN kraj_fajla := 1;
end;
end loop;
update zivot_trajni_nalog_ponude set redni_broj = p_rbr;
commit;
text_io.fclose(import_file);
message('Zavrseno prepisivanje fajla');
end;
The error you got (ORA-01407) means that you are trying to update a column (which is set to NOT NULL) with a NULL value. That won't work. For example:
SQL> create table test (id number not null);
Table created.
SQL> insert into test (id) values (100);
1 row created.
SQL> update test set id = null;
update test set id = null
*
ERROR at line 1:
ORA-01407: cannot update ("SCOTT"."TEST"."ID") to NULL
SQL>
The only UPDATE in your code is this:
UPDATE zivot_trajni_nalog_ponude SET redni_broj = p_rbr;
Apparently, p_rbr is NULL, redni_broj won't accept it and you got the error.
What to do? Debug your code and see why p_rbr doesn't have a value. A simple "solution" might be
IF p_rbr IS NOT NULL
THEN
UPDATE zivot_trajni_nalog_ponude
SET redni_broj = p_rbr;
END IF;
Also, although not related to your problem: don't COMMIT within a loop.
ORA-01407 occurs as you are trying to update/Insert a column to NULL
when the column does not accept NULL values.
To find all the "not null" columns in table ZIVOT_TRAJNI_NALOG_PONUDE, Please check the DDL of the table.

Checking the date before inserting in a table ORACLE 10g

I have table:
BOOK_DT1 BOOK_DT2 USERNAME
--------- --------- --------------------
22-SEP-17 12-OCT-17 rSK
08-FEB-16 18-FEB-16 chak
05-JAN-17 12-JAN-17 rah
31-JAN-16 01-JUL-16 ABC
While inserting another column, it should check the given dates for BOOK_DT1 and BOOK_DT2 should not come into the dates present in the table.
For EX: insert into table_name('28-SEP-17','12-NOV-17','XYX'); should throw an error, because '28-SEP-17' comes in between 22-SEP-17 and 12-OCT-17.
you can achive this using the after insert trigger. Somting like this:
create or replace trigger date_check_trg
after insert
on your_table_name
v_cnt NUMBER;
begin
select count(*)
into v_cnt
from you_table_name t1
join you_table_name t2
on ( t1.BOOK_DT1 between t2.BOOK_DT1 and t2.BOOK_DT1
or t1.BOOK_DT2 between t2.BOOK_DT1 and t2.BOOK_DT1
)
AND t1.rowid != t2.rowid
;
if v_cnt > 0 then
raise_application_error(-20999, 'intersection error');
end if;
end;
/
If you want to check before the insert then BEFORE INSERT should be what you're looking for. If the name doesn't matter and your new values should not be between any values previously inserted in the table then this is how I would write it:
create or replace trigger trg_date_chk
before insert
on your_table_name for each row
declare
lnCnt NUMBER;
begin
select count(*)
into lnCnt
from you_table_name a
where :new.BOOK_DT1 < a.BOOK_DT1
and :new.BOOK_DT2 > a.BOOK_DT2;
if lnCnt > 0 then
raise_application_error(-20999, 'INSERT ERROR HERE');
end if;
end;
/

Trigger, at line 1 ORA 04098

Hi im setting up some triggers and i cant get past this error
SET SERVEROUTPUT ON
CREATE OR REPLACE TRIGGER trigger2
BEFORE INSERT ON new_donation
FOR EACH ROW
--WHEN (new.contamt <= 10)
DECLARE
v_idno VARCHAR2(5);
v_driveno VARCHAR2(3);
v_contdate DATE;
v_contamt NUMBER(6,2);
BEGIN
SELECT IDNO, DRIVENO, CONTDATE, CONTAMT INTO v_idno, v_driveno, v_contdate, v_contamt
FROM OLD_DONATION2
WHERE IDNO = :new.idno;
IF :new.contamt < 50 THEN
RAISE_APPLICATION_ERROR (-20001, 'CONTRIBUTION TOO LOW FOR '
|| :new.idno || ' ' || :new.contamt);
END IF;
END;
/
SET SERVEROUTPUT OFF
another part
DECLARE
v_idno new_donation.idno%TYPE := '&in_idno';
v_driveno new_donation.driveno%TYPE := '&in_driveno';
v_contdate new_donation.contdate%TYPE := '&in_contdate';
v_contamt new_donation.contamt%TYPE := &in_contamt;
BEGIN
INSERT INTO new_donation
VALUES (v_idno, v_driveno, v_contdate, v_contamt);
END;
/
Im getting this error when I insert values at trigger2.
ERROR at line 1: ORA-04098: trigger 'XXXXXXXXX.NEW_DONATION' is
invalid and failed re-validation ORA-06512: at line 7
All im trying to do is insert some values input by the user to this new table, which is empty.
Also when donation amount is < 10 I want a error out.
Follow these steps.
Run this query select status from all_objects where object_name = 'TBL_USER_TRIGGER' and object_type = 'TRIGGER';
If the status is invalid run alter trigger trigger2 compile;
Then run show errors
It will throw the errors for you. You need to fix those.

How to develop an after serverror trigger in Oracle?

I'm trying to log all the errors in my database into a table. So as user sys i wrote the following code:
CREATE TABLE servererror_log (
error_datetime TIMESTAMP,
error_user VARCHAR2(30),
db_name VARCHAR2(9),
error_stack VARCHAR2(2000),
captured_sql VARCHAR2(1000));
/
CREATE OR REPLACE TRIGGER log_server_errors
AFTER SERVERERROR
ON DATABASE
DECLARE
captured_sql VARCHAR2(1000);
BEGIN
SELECT q.sql_text
INTO captured_sql
FROM gv$sql q, gv$sql_cursor c, gv$session s
WHERE s.audsid = audsid
AND s.prev_sql_addr = q.address
AND q.address = c.parent_handle;
INSERT INTO servererror_log
(error_datetime, error_user, db_name,
error_stack, captured_sql)
VALUES
(systimestamp, sys.login_user, sys.database_name,
dbms_utility.format_error_stack, captured_sql);
END log_server_errors;
But when i force an error like trying to select from a non-existing table it doesn´t log the error in the table.
Is there any way to check that the trigger fires at all? Also, I tried creating a test table to insert there but it doesn't work either, even if a define the trigger as an autonomous transaction and commit inside the trigger.
Thanks,
Joaquin
Do not query v$sql; get the statement using ora_sql_txt.
CREATE OR REPLACE TRIGGER log_server_errors
AFTER SERVERERROR
ON DATABASE
DECLARE
sql_text ora_name_list_t;
stmt clob;
n number;
BEGIN
n := ora_sql_txt(sql_text);
if n > 1000 then n:= 1000; end if ;
FOR i IN 1..n LOOP
stmt := stmt || sql_text(i);
END LOOP;
INSERT INTO servererror_log
(error_datetime, error_user, db_name,
error_stack, captured_sql)
VALUES
(systimestamp, sys.login_user, sys.database_name,
dbms_utility.format_error_stack, stmt);
commit;
END log_server_errors;
/
Then:
SQL> select * from c;
This produces:
select * from c
*
ERROR at line 1:
ORA-00942: table or view does not exist
That can now be queried:
select * from servererror_log;
To produce:
ERROR_DATETIME
---------------------------------------------------------------------------
ERROR_USER DB_NAME
------------------------------ ---------
ERROR_STACK
--------------------------------------------------------------------------------
CAPTURED_SQL
--------------------------------------------------------------------------------
11-FEB-09 02.55.35.591259 PM
SYS TS.WORLD
ORA-00942: table or view does not exist
select * from c
To see if the trigger is firing, add one or more lines to it like this:
DBMS_OUTPUT.PUT_LINE( 'Got this far' );
In SQLPlus, SET SERVEROUTPUT ON then execute a command to generate an error. You should get output like this:
dev> select * from aldfjh;
select * from aldfjh
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-00942: table or view does not exist
Got this far
Check the status of your trigger and/or the existence of other triggers with:
select trigger_name, status
from all_triggers
where triggering_event like 'ERROR%'
This should result into:
TRIGGER_NAME STATUS
------------ -------
LOG_SERVER_ERRORS ENABLED
If trigger is not enabled or another trigger fails, it probably will not work.
Save this as ORA-00942.sql:
-- Drop trigger and ignore errors (e.g., not exists).
DECLARE
existential_crisis EXCEPTION;
PRAGMA EXCEPTION_INIT( existential_crisis, -4080 );
BEGIN
EXECUTE IMMEDIATE 'DROP TRIGGER TRG_CATCH_ERRORS /*+ IF EXISTS */';
EXCEPTION WHEN existential_crisis THEN
DBMS_OUTPUT.PUT_LINE('Ignoring non-existence.');
END;
/
-- Drop table and ignore errors (e.g., not exists).
DECLARE
existential_crisis EXCEPTION;
PRAGMA EXCEPTION_INIT( existential_crisis, -942 );
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE TBL_ERROR_LOG /*+ IF EXISTS */';
EXCEPTION WHEN existential_crisis THEN
DBMS_OUTPUT.PUT_LINE('Ignoring non-existence.');
END;
/
-- Create the table (will not exist due to drop statement).
CREATE TABLE TBL_ERROR_LOG (
occurred timestamp,
account varchar2(32),
database_name varchar2(32),
stack clob,
query clob
);
-- Create the trigger to log the errors.
CREATE TRIGGER TRG_CATCH_ERRORS AFTER servererror ON database
DECLARE
sql_text ora_name_list_t;
n number;
query_ clob;
BEGIN
n := ora_sql_txt( sql_text );
IF n > 1000 THEN n := 1000; END IF;
FOR i IN 1 .. n LOOP
query_ := query_ || sql_text( i );
END LOOP;
INSERT INTO TBL_ERROR_LOG
(occurred, account, database_name, stack, query)
VALUES
(systimestamp, sys.login_user, sys.database_name,
dbms_utility.format_error_stack, query_);
END;
/
Run using sqlplus:
SQL> #ORA-00942.sql
PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed.
Table created.
Trigger created.
Test it:
select * from blargh;
select * from TBL_ERROR_LOG;
Output:
2017-10-20 15:15:25.061 SCHEMA XE "ORA-00942: table or view does not exist" select * from blargh

Resources