a double-quoted delimited-identifier error SQL - oracle

Hi everyone am experiencing this error in oracle
Errors: TRIGGER NOUPDATE
Line/Col: 9/5 PLS-00103: Encountered the symbol "IF" when expecting one of the following:
; <an identifier> <a double-quoted delimited-identifier>
This is the code:
CREATE OR REPLACE TRIGGER NoUpdate
BEFORE UPDATE OF apartmentsize ON rental
FOR EACH ROW
DECLARE
apartmentsize INT(22);
BEGIN
IF (apartmentsize < 60) THEN
BEGIN
RAISE_APPLICATION_ERROR(-20112,
'You cannot update the apartmentsize');
ROLLBACK;
END IF;
END;
/

I think it's firing the trigger but the IF condition is never true. I don't see anywhere that you assign a value to apartmentsize.
If you think it is this statement:
apartmentsize int(22);
Then no, that is simply saying that aparmentsize is declared as a 22-digit integer. If you want to assign a value:
apartmentsize int := 22;
And according to the 18c SQL Language Reference, 'int' is not a valid data type. Supported numeric data types are:
number
float
binary_float
binary_double
What you want is NUMBER(precision,scale). See here.

You have a BEGIN without an END and you probably want to use :NEW.apartmentsize bind variable to reference the updated value rather than declaring a variable in the trigger:
CREATE OR REPLACE TRIGGER NoUpdate
BEFORE UPDATE OF apartmentsize ON rental
FOR EACH ROW
DECLARE
BEGIN
IF (:NEW.apartmentsize < 60) THEN
RAISE_APPLICATION_ERROR(
-20112,
'You cannot update the apartmentsize'
);
END IF;
END;
/
(Note: Including ROLLBACK is pointless as raising the exception will implicitly trigger a rollback and once you have raised the exception the rest of the code in the trigger will not be parsed as an exception has been raised.)
Then if you have the table:
CREATE TABLE rental ( id, apartmentsize ) AS
SELECT 1, 100 FROM DUAL;
Then:
UPDATE rental
SET apartmentsize = 60
WHERE id = 1;
Will work but:
UPDATE rental
SET apartmentsize = 59
WHERE id = 1;
Will raise the exception:
ORA-20112: You cannot update the apartmentsize
ORA-06512: at "FIDDLE_DAVWBSJBRDBITOSDOROT.NOUPDATE", line 4
ORA-04088: error during execution of trigger 'FIDDLE_DAVWBSJBRDBITOSDOROT.NOUPDATE'
db<>fiddle here

Related

can anyone help me with the trigger insert problem i created?

so I made a trigger insert like this:
create or replace trigger discount
after insert on transaction
for each row
begin
if (new.desc_date = 'Y') then
insert into desc_transaction(discount) values (new.discount = '0.1');
end if;
end;
/
Warning: Trigger created with compilation errors.
show error;
3/1 PL/SQL: SQL Statement ignored
3/54 PL/SQL: ORA-00917: missing comma
how to solve it.
data :
desc_date contains only yes and no because if November is discounted and October is not.
For the discount section contains 0.1 and null so if desc_date is yes then 0.1 otherwise it will be null or ' '.
Wrong syntax. Should've been
CREATE OR REPLACE TRIGGER discount
AFTER INSERT
ON transaction
FOR EACH ROW
BEGIN
IF :new.desc_date = 'Y'
THEN
INSERT INTO desc_transaction (discount)
VALUES (0.1);
END IF;
END;
/
Or, possibly even better,
CREATE OR REPLACE TRIGGER discount
AFTER INSERT
ON transaction
FOR EACH ROW
BEGIN
INSERT INTO desc_transaction (discount)
VALUES (CASE WHEN :new.desc_date = 'Y' THEN 0.1 ELSE NULL END);
END;
/
The syntax of your insert statement is incorrect. Try the following:
insert into desc_transaction(discount) values ('0.1');
Side note - discount probably isn't a varchar column. If this guess is correct, you should be using a numeral literal (0.1) and not a string literal ('0.1') like you currently have.

Oracle Trigger To Check Values On Insert & Update

I am trying to check a value-gap crossed with each other or not. Let me explain with a quick scenario.
Rec 1 : Company AA : Distance Gap -> 100 - 200
Rec 2 : Company AA : Distance Gap -> 200 - 300 VALID
Rec 3 : Company AA : Distance Gap -> 250 - 450 INVALID
Rec 4 : Company JL : Distance Gap -> 250 - 450 VALID
Rec 3 Invalid because it is between REC 2's distance values.
Rec 4 Valid because company is different
Thus I wrote a trigger to prevent it.
create or replace trigger ab_redemption_billing_mpr
after insert or update on redemption_billing_mpr
for each row
declare
v_is_distance_range_valid boolean;
begin
v_is_distance_range_valid := p_redemption_billing.is_distance_range_valid(:new.id,
:new.redemption_billing_company,
:new.distance_min,
:new.distance_max,
'redemption_billing_mpr');
if not v_is_distance_range_valid then
raise_application_error(-20001, 'This is a custom error');
end if;
end ab_redemption_billing_mpr;
FUNCTION:
function is_distance_range_valid(p_id in number,
p_company in varchar2,
p_distance_min in number,
p_distance_max in number,
p_table_name in varchar2) return boolean is
d_record_number number;
begin
execute immediate 'select count(*) from ' || p_table_name || ' r
where r.redemption_billing_company = :1
and (:2 between r.distance_min and r.distance_max or :3 between r.distance_min and r.distance_max)
and r.id = nvl(:4, id)'
into d_record_number
using p_company, p_distance_min, p_distance_max, p_id;
if (d_record_number > 0) then
return false;
else
return true;
end if;
end;
is_distance_range_valid() works just as I expected. If it returns false, that means range check is not valid and don't insert or update.
When I create a scenario to catch this exception, oracle gives
ORA-04091: table name is mutating, trigger/function may not see it
and it points select count(*) line when I click debug button.
I don't know why I am getting this error. Thanks in advance.
Just check whether the below approach resolves your issue
Create a log table with columns required for finding the is_distance_range_valid validation and In your trigger insert into this log tab.The trigger on main table has to be a before insert or update trigger
Create a trigger on this log table and do the validation in the log table trigger and raise error.The trigger on log table has to be an after insert or update trigger.
Also this will only work if the row is already existing in the main table and it is not part of the current insert or update. If validation of the current insert or update is required then we need to use the :new.column_name to do the validation
Test:-
create table t_trg( n number);
create table t_trg_log( n number);
create or replace trigger trg_t
before insert or update on t_trg
for each row
declare
l_cnt number;
begin
insert into t_trg_log values(:new.n);
end trg_t;
create or replace trigger trg_t_log
after insert or update on t_trg_log
for each row
declare
l_cnt number;
begin
select count(1) into l_cnt from t_trg
where n=:new.n;
if l_cnt > 0 then
raise_application_error(-20001, 'This is a custom error');
end if;
end trg_t_log;
The first time I insert it doesn't throw error
insert into t_trg values(7);
1 row inserted.
The second time I execute, I get the custom error
insert into t_trg values(7);
Error report -
ORA-20001: This is a custom error
ORA-06512: at "TRG_T_LOG", line 7
ORA-04088: error during execution of trigger 'TRG_T_LOG'
ORA-06512: at "TRG_T", line 4
ORA-04088: error during execution of trigger 'TRG_T'
Update:-Using compound trigger the error is thrown in the first time the insert is done since it also takes into account the current row that we are updating or inserting while doing the SELECT
First I want to thanks to psaraj12 for his effort.
I found solution. Oracle forces us to not use select query before each row.
Oracle trigger error ORA-04091
So I wrote this and it works.
create or replace trigger ab_redemption_billing_mpr
for insert or update on redemption_billing_mpr
compound trigger
v_is_distance_range_valid boolean;
id redemption_billing_mpr.id%type;
redemption_billing_company redemption_billing_mpr.redemption_billing_company%type;
distance_min redemption_billing_mpr.distance_min%type;
distance_max redemption_billing_mpr.distance_max%type;
after each row is
begin
id := :new.id;
redemption_billing_company := :new.redemption_billing_company;
distance_min := :new.distance_min;
distance_max := :new.distance_max;
end after each row;
after statement is
begin
v_is_distance_range_valid := p_redemption_billing.is_distance_range_valid(id,
redemption_billing_company,
distance_min,
distance_max,
'redemption_billing_mpr');
if not v_is_distance_range_valid then
raise_application_error(-20001, 'This is a custom error');
end if;
end after statement;
end ab_redemption_billing_mpr;
We must use compound trigger to deal with it.

Trying to create a trigger but get error PLS-00103

create or replace trigger newcontract
before insert on contract
declare numcon int;
for each row
begin
select contractcount
into numcon from task
where task.taskid = old.taskid;
if numcon < 3 then
insert into contract values(taskid, workerid, payment);
else
dbms_output.put_line('task is full');
end if;
end;
Gives this cryptic error
Error(1,5): PLS-00103: Encountered the symbol "FOR" when expecting one of the following: begin function pragma procedure subtype type <an identifier> <a double-quoted delimited-identifier> current cursor delete exists prior
The record being inserted into contract should not be inserted if contract count for that task is about 2. So I need to check the value of contractcount for each record being inserted. I use a select statement to get the value, but I get this error.
You have more than one problem here:
declare section(the part of the trigger where you declare your variables) goes after the for each row part
OLD and NEW values are "accessed" like this : :new.column_name and :old.column_name
The :old value in before insert trigger is always null because you are inserting a new value, there is no old value, only new value.
If you want to prevent insert if some value is smaller than 3 then you can do it like this:
create or replace trigger newcontract
before insert on contract
for each row
declare
numcon int;
begin
select contractcount
into numcon
from task
where task.taskid = :new.taskid;
if numcon < 3 then
raise_application_error(-20000, 'Task is full');
end if;
end;
/
Here is a small demo
For more info please do add some more detailed description and some sample data where you show us what kind of data you want to be able to insert and why and what kind of data you do not want to insert and why.

Oracle SQL Trigger for set min Value to INT Field on NULL

I am trying to get a trigger on the table PACKS that set a min Value in INT Field - PRICE when inserting a new PACK - for example '333'. for insert calling a Procedure new pack.
thats the trigger:
CREATE OR REPLACE TRIGGER pack_min_price
BEFORE
INSERT
ON PACKS
FOR EACH ROW
BEGIN
IF new.PRICE < 333 THEN
:new.PRICE := :new.PRICE + 333;
END IF;
END;
and thats the PROCEDURE:
create or replace PROCEDURE newPack(
cntr IN PACKS.COUNTRY%TYPE,
trns IN PACKS.TRANSPORT%TYPE,
htl IN PACKS.HOTEL%TYPE,
extr IN PACKS.HOTELEXTRAS%TYPE,
othextr IN PACKS.OTHEREXTRAS%TYPE,
strdt IN PACKS.STARTDATE%TYPE,
enddt IN PACKS.ENDDATE%TYPE,
prc IN PACKS.PRICE%TYPE)
IS
BEGIN
INSERT INTO PACKS
(COUNTRY,TRANSPORT,HOTEL,HOTELEXTRAS,OTHEREXTRAS,STARTDATE,ENDDATE,PRICE)
VALUES
(cntr,trns,htl,extr,othextr,strdt,enddt,prc);
COMMIT;
END;
the error i get when i try to compile the trigger -
Compilation failed, line 2 (10:12:41) The line numbers associated with compilation errors are relative to the first BEGIN statement. This only affects the compilation of database triggers.
PLS-00201: identifier 'NEW.PRICE' must be declaredCompilation failed, line 2 (10:12:41) The line numbers associated with compilation errors are relative to the first BEGIN statement. This only affects the compilation of database triggers.
PL/SQL: Statement ignored
and when i start the procedure -
ORA-04098: trigger 'PROJECT160.PACK_MIN_PRICE' is invalid and failed re-validation
without the Trigger the Procedure is working perfectly fine. Can you help? thx
You are missing the : on the new instance in the IF statement.
IF :new.PRICE < 333 THEN
:new.PRICE := :new.PRICE + 333;
END IF;

Handle an exception in a trigger in oracle

I'm a rookie in oracle and I want to display an error when (expAnnee*100 + expMois) < YYMM (YYMM of SYSDATE) to check the validity of a credit card.
expAnnee and expMois are numbers.
I get the following error:
PLS-00201: identifier 'NEW.EXPANNEE' must be declared
But this is a trigger, and in my "InfoCredit" table expAnnee and expMois are indeed there.
CREATE OR REPLACE TRIGGER VALID_CARD
BEFORE INSERT ON INFOCREDIT
FOR EACH ROW
DECLARE
ex_expired EXCEPTION;
testdate NUMBER;
BEGIN
SELECT to_number(to_char(to_date(SYSDATE, 'DD-MM-YYYY'), 'YYMM'))
INTO testdate
FROM Dual;
if ((new.expAnnee*100+new.expMois) < testdate)
Then RAISE ex_expired;
END IF;
EXCEPTION
WHEN ex_expired
THEN DBMS_OUTPUT.PUT_LINE('CARD EXPIRED');
END;
/
Refer to new as :new
E.g.
if ((:new.expAnnee*100+:new.expMois) < testdate)

Resources