PLSQL_trigger duplicate a# has errors - plsql

I created this trigger that prevents duplicate acct# to be added. But when I tested the trigger by inserting a duplicate acct#, I got error
UNIQUE CONSTRAINT (JL.PK.ACCOUNT) VIOLATED
Please help.
create or replace trigger update_acct#
before insert or update on ACCOUNT
for each row
declare
v_cta# NUMBER;
begin
select count(A#) into v_cta# from account where A#=:new.A#;
if v_cta#>1 then
raise_application_error (-20105, 'DUPLICATE ACCOUNT NUMBER');
end if;
end;

Your trigger did not throw the error. It didn't even fire.
You did not post the table definition from the error provided but it looks like the column A# in define as the primary key. When you attempted to insert the duplicate row the error was thrown as the PK was validated. You do not have to check primary key for duplicates: Oracle guarantees it is unique.
Further had you trigger fired you would have gotten a "ORA-04091 table Name is mutating ... " error. You cannot reference the triggering table within a row level trigger.

You should if condition:
--old code
if v_cta#>1 then
raise_application_error (-20105, 'DUPLICATE ACCOUNT NUMBER');
end if;
--new code
if v_cta#>0 then
raise_application_error (-20105, 'DUPLICATE ACCOUNT NUMBER');
end if;
When v_cta# equals 1 then your condition will not work

Related

oracle trigger to prevent insert operation

based on role number I am trying to prevent the insert operation. If role number>=103 it should deny.
CREATE OR REPLACE TRIGGER ins_table
BEFORE INSERT ON Tables
FOR EACH ROW
DECLARE
userole number
BEGIN
SELECT role into userole FROM User_account where user_id = :new.user_id;
IF (userole >= 103)
THEN
RAISE_APPLICATION_ERROR(-20001,'Access denied');
END IF;
END;
The above trigger causes an compilation error

Trigger for checking values for inserting

I have two tables that here are involved from two different schemas.
Schema services and table task -- column ID
Schme mona_internal and table officius_unos -- column task
I need trigger when inserting in column task table officius_unos to check does exist inserting value in column id from table task. If exist, to continue inserting, it doesn't exist to raise the error.
Here is the trigger:
CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA
BEFORE INSERT ON OFFICIUS_UNOS
FOR EACH ROW
DECLARE
task_provera number(10);
BEGIN
select id into task_provera from servis.task
where id=:new.task;
if (task_provera is null)
then raise_application_error(-20101, 'No task');
else insert into mona_internal.OFFICIUS_UNOS (task) values (:new.task);
end if;
END;
The trigger is compiled, but the problem appears when trying to insert a new value in column task table officius_unos,
it returns me this message
insert into officius_unos (task) values (291504);
Error report -
ORA-00036: maximum number of recursive SQL levels (50) exceeded
ORA-00036: maximum number of recursive SQL levels (50) exceeded
ORA-06512: at "MONA_INTERNAL.PROBA_PROBA", line 5
ORA-04088: error during execution of trigger 'MONA_INTERNAL.PROBA_PROBA'
ORA-06512: at "MONA_INTERNAL.PROBA_PROBA", line 10
And value 291504 exist in table task in column id.
P.S. Also try to solve this problem with check constraint, but there are forbidden subqueries. The solution that I used to overcome my problem is here
Oracle: Using subquery in a trigger
You don't need to insert in an insert trigger.
If the trigger is successful Oracle will continue with the INSERT on its own.
So the immediate solution is to remove the INSERT from the trigger:
CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA
BEFORE INSERT ON OFFICIUS_UNOS
FOR EACH ROW
DECLARE
task_provera number(10);
BEGIN
select id
into task_provera
from servis.task
where id=:new.task;
if (task_provera is null) then
raise_application_error(-20101, 'No task');
end if;
// nothing do do here
END;
However the above still isn't correct. If the id doesn't exist in servis.tak the SELECT will throw a NO_DATA_FOUND exception.
One solution to that is to use an aggregate function that will always return one row. If no rows match the WHERE criteria, a NULL value is returned:
CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA
BEFORE INSERT ON OFFICIUS_UNOS
FOR EACH ROW
DECLARE
task_provera number(10);
BEGIN
select max(id)
into task_provera
from servis.task
where id=:new.task;
if (task_provera is null) then
raise_application_error(-20101, 'No task');
end if;
// nothing do do here
END;
Or you could explicitely catch the exception:
CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA
BEFORE INSERT ON OFFICIUS_UNOS
FOR EACH ROW
DECLARE
task_provera number(10);
BEGIN
select max(id)
into task_provera
from servis.task
where id=:new.task;
if (task_provera is null) then
raise_application_error(-20101, 'No task');
end if;
EXCEPTION
WHEN NOT_DATA_FOUND THEN
raise_application_error(-20101, 'No task');
END;
But the correct approach is to use a foreign key constraint for something like that.
alter table mona_internal.PROBA_PROBA
add constraint fk_proba_task
foreign key (task)
references servis.task (id);
Then you don't need a trigger at all.
This requires that the user mona_internal is not only granted the SELECT privilege on servis.task, but also the references privilege:
To do that, run the following as the SERVIS user:
grant references on task to mona_internal;

Warning: Trigger created with compilation errors?

I am trying to implement Trigger that raises an User Defined Error Message and does not allow the update and Insert operation in the database.I am new to pl/sql i refereed some code from the internet and try to implement.My code is running is fine as i can not update/insert into database but still i am unable to get my user defined message and also i am getting this warning.
Warning: Trigger created with compilation errors ?
This is the table :
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER(5)
NAME VARCHAR2(20)
SALARY NUMBER(10)
DEPOT_ADDRESS VARCHAR2(15)
here is my code :
create or replace trigger cleaner_before_update_insert
for update or insert on cleaner
compound trigger
count binary_integer;
before statement is
begin
count:=0;
end before statement;
after each row is
begin
count :=count +1;
end after each row;
after statement is
begin
if count > 0 then
raise_application_error( -20001,'Update/insert operation can not be completed ');
end if;
end after statement;
end cleaner_before_update;
/
can anyone help me figure out what is the problem here and way to fix it.
thanks in advance.
Even after compilation of the code it is giving me this error.
ORA-06512: at "SYSTEM.CLEANER_BEFORE_UPDATE_INSERT", line 18
ORA-04088: error during execution of trigger
'SYSTEM.CLEANER_BEFORE_UPDATE_INSERT'
There are couple of problems with your TRIGGER block.
The name of the Trigger cleaner_before_update_insert does not match with the cleaner_before_update after the final end statement.
COUNT is an SQL keyword which is not allowed to be used as a variable in PL/SQL.You would receive the error - Error(10,11): PLS-00204: function or pseudo-column 'COUNT' may be used inside a SQL statement only
So, here is the modified code.
CREATE OR REPLACE TRIGGER cleaner_before_update_insert FOR UPDATE OR
INSERT ON cleaner compound TRIGGER
v_count binary_integer;
before STATEMENT
IS
BEGIN
v_count:=0;
END before STATEMENT;
AFTER EACH row
IS
BEGIN
v_count :=v_count +1;
END AFTER EACH row;
AFTER STATEMENT
IS
BEGIN
IF v_count > 0 THEN
raise_application_error( -20001,'Update/insert operation can not be completed ');
END IF;
END AFTER STATEMENT;
END cleaner_before_update_insert;
/

PLSQL_trigger_check duplicate account number has erros

Trying to create a trigger that prevents duplicate acct# and null acct balance. Trigger is able to create but when inserting an duplicate acct# to test the trigger, got error mesg that "trigger is invalid and failed re-validation".
create or replace trigger update_acct#
before insert or update on ACCOUNT
for each row
declare
v_cta# NUMBER;
begin
select count(:new.A#) into v_cta# from account group by A#;
if (v_cta#>1 or :new.bal=null) then
raise_application_error (-20011, 'DUPLICATE ACCOUNT NUMBER OR BAL CANNOT BE NULL');
end if;
end;
You absolutely positively do not want to use a trigger for this. Use a unique constraint to prevent duplicate account numbers.
ALTER TABLE account ADD CONSTRAINT a#_unique UNIQUE (a#);
Make your balance field not accept nulls.
ALTER TABLE account MODIFY bal NOT NULL;
For purely educational purposes here is how you'd implement this with your trigger. Yours was close, except you want to use :new.a# to count rows and not have it expressly in the COUNT() and that you want an AFTER trigger since you want to see if your newly added account is the first duplicate.
create or replace trigger update_acct#
after insert or update on ACCOUNT
for each row
DECLARE
v_cta# INTEGER;
BEGIN
SELECT COUNT(*)
INTO v_cta#
FROM account
WHERE a# = :new.a#;
IF v_cta# > 1 OR :new.bal = NULL THEN
raise_application_error(-20011,
'DUPLICATE ACCOUNT NUMBER OR BAL CANNOT BE NULL');
END IF;
END update_acct#;
/

Display custom message when constraint is violated PL/SQL

I'm writing a pl/sql procedure. I've got a constraint on a column which doesn't allow values below 0 and above 500. I need to display a custom message if this constraint is violated (eg. "ID out of range"). Currently this is the exception and also the output in getting. There is another procedure that is outputting the error, hence the use raise_applcation_error.
Exception
when VALUE_ERROR then
raise_application_error(-20002, 'Customer ID out of range');
Error Message
"ORA-20000: ORA-02290: check constraint (s5849497.CK_ID_RANGE) violated"
What I would like
"ORA-20000: Customer ID out or range"
Here is the whole block if it helps
set serveroutput on;
---------------------------------------------------------------
alter table customer
add constraint ck_id_range
check (custid > 0 and custid < 500);
---------------------------------------------------------------
create or replace procedure ADD_CUSTOMER_TO_DB(pcustid number, pcustname varchar2) as
begin
insert into customer
values (pcustid,pcustname,0,'OK');
exception
when DUP_VAL_ON_INDEX then
raise_application_error(-20001, 'Duplicate customer ID');
when VALUE_ERROR then
raise_application_error(-20002, 'Customer ID out of range');
when others then
raise_application_error(-20000, SQLERRM);
end;
Thank you
I'm guessing that you're getting an ORA-02290 error. The way to catch this in an exception handler is to declare and initialize an exception for the particular error code (in this case, -2290) and then use your custom exception in the handler:
create or replace procedure ADD_CUSTOMER_TO_DB(pcustid number,
pcustname varchar2)
as
eCheck_constraint_violated EXCEPTION;
PRAGMA EXCEPTION_INIT(eCheck_constraint_violated, -2290);
begin
insert into customer
values (pcustid,pcustname,0,'OK');
exception
when DUP_VAL_ON_INDEX then
raise_application_error(-20001, 'Duplicate customer ID');
when eCheck_constraint_violated then
raise_application_error(-20002, 'Customer ID out of range');
when others then
raise_application_error(-20000, SQLERRM);
end;
As you'll see above, I just replaced VALUE_ERROR with the newly-defined exception.
If by chance the error you're getting is not -2290, just put the error you're seeing in PRAGMA EXCEPTION_INIT invocation above instead of -2290.
Share and enjoy.

Resources