I am trying to create a trigger on ComputerTable to update the insert operation in TableWithTrigger
I have SemesterID in SemesterDim table and TimeID in TimePeriodDim table. I declare the two variables at the beginning to call the other two attributes and update the TempSemesterID and TempTimeID with a value by comparing conditions.
Here is my code:
create or replace trigger UpdateTrigger
after insert on ComputerTable
referencing new as new old as old
for each row
declare
TempSemesterID SemesterDim.SemesterID%type;
TempTimeID TimePeriodDim.TimeID%type;
begin
if (to_char(LoginDate, 'MM/DD') >= '01/01')
and (to_char(LoginDate, 'MM/DD') <= '07/15') then
TempSemesterID := 'S1';
else
TempSemesterID := 'S2';
end if;
if (to_char(LoginTime, 'HH24:MI') >= '06:00')
and (to_char(LoginTime, 'HH24:MI') < '12:00') then
TempTimeID := '1';
elsif (to_char(LoginTime, 'HH24:MI') >= '12:00')
and (to_char(LoginTime, 'HH24:MI') < '18:00') then
TempTimeID := '2';
else
TempTimeID := '3';
end if;
insert into TableWithTrigger
values (:new.LoginTime, :new.LoginDate,
:new.DegreeCode, :new.StudentNo, TempSemesterID, TempTimeID);
end UpdateTrigger;
/
I got errors like :
Error(70,3): PL/SQL: Statement ignored;
Error(70,15): PLS-00201: identifier 'LOGINDATE' must be declared;
Error(77,3): PL/SQL: Statement ignored;
Error(77,15): PLS-00201: identifier 'LOGINTIME' must be declared;
I have no ideas on how to fix them, hope someone can help me with it.
When you refer to column names in your table that the trigger is on, you need to use either :old. or :new. prefixes so the code will know whether you are referencing the old value or the new value.
The :new notation applies to columns on the owning table. It looks like you are trying to populate local variables. So, just remove the namespace from the assignments. Note that you need to include :new. when you are referencing a column. Your IF statements reference table columns, so you need to add :new. to those references, like this:
if (to_char(:new.LoginDate, 'MM/DD') >= '01/01')
and (to_char(:new.LoginDate, 'MM/DD') <= '07/15') then
TempSemesterID := 'S1';
else
TempSemesterID := 'S2';
end if;
PLS-00103: Encountered the symbol "UpdateTrigger" when expecting one of the following: if
You got that error because you used ELSE IF in the switch statement, In PL/SQL the correct syntax is ELSIF. As you have it, you have started a nested IF block, and the compiler is expecting end UpdateTrigger; to be the matching end if statement.
Here is a version of your code which compiles:
create or replace trigger UpdateTrigger
after insert on ComputerTable
for each row
declare
TempSemesterID SemesterDim.SemesterID%type;
TempTimeID TimePeriodDim.TimeID%type;
begin
if (to_char(:new.LoginDate, 'MM/DD') >= '01/01')
and (to_char(:new.LoginDate, 'MM/DD') <= '07/15') then
TempSemesterID := 'S1';
else
TempSemesterID := 'S2';
end if;
if (to_char(:new.LoginTime, 'HH24:MI') >= '06:00')
and (to_char(:new.LoginTime, 'HH24:MI') < '12:00') then
TempTimeID := '1';
elsif (to_char(:new.LoginTime, 'HH24:MI') >= '12:00')
and (to_char(:new.LoginTime, 'HH24:MI') < '18:00') then
TempTimeID := '2';
else
TempTimeID := '3';
end if;
insert into TableWithTrigger
values (:new.LoginTime, :new.LoginDate,
:new.DegreeCode, :new.StudentNo, TempSemesterID, TempTimeID);
end UpdateTrigger;
/
Here is a demo on db<>fiddle
Related
I am a beginner using PL/SQL in oracle database, I just want to develop the coding that has been exist before. I want to put new condition and statement IF THEN ELSE NESTED after this code ELSIF updating THEN H_TYP := 'U';
But I am stuck with the my code, I have not yet find the way to fixing my code.
Here is my code;
create or replace TRIGGER TMCI_SUB_ITEM_MASTER_TR_R
AFTER DELETE OR INSERT OR UPDATE ON TMCI_SUB_ITEM_MASTER
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
BEGIN
DECLARE
H_ID TMCI_SUB_ITEM_MASTER_R.HST_ID%TYPE;
H_TYP TMCI_SUB_ITEM_MASTER_R.TSK%TYPE;
rdate DATE;
t_max_rev TMCI_SUB_ITEM_MASTER_R.REV%TYPE;
H_INS_USR_ID TMCI_SUB_ITEM_MASTER_R.INS_USR_ID%TYPE;
BEGIN
rdate := SYSDATE;
IF INSERTING THEN H_TYP := 'I';
...
ELSIF updating THEN H_TYP := 'U';
IF H_INS_USR_ID = 'SL01' THEN
SELECT NVL(MAX(Rev), 0) INTO t_max_rev FROM TMCI_SUB_ITEM_MASTER_R WHERE ITM_CD = :old.ITM_CD;
INSERT INTO TMCI_SUB_ITEM_MASTER_R
VALUES( H_ID,
H_TYP,
:old.ITM_CD,
CASE WHEN :old.ITM_NM <> :new.ITM_NM THEN CONCAT(:new.ITM_NM,'')
ELSE :new.ITM_NM
END);
ELSE
SELECT NVL(MAX(Rev), 0) INTO t_max_rev FROM TMCI_SUB_ITEM_MASTER_R WHERE ITM_CD = :old.ITM_CD;
INSERT INTO TMCI_SUB_ITEM_MASTER_R
VALUES( H_ID,
H_TYP,
:old.ITM_CD,
CASE WHEN :old.ITM_NM <> :new.ITM_NM THEN CONCAT(:new.ITM_NM,'*')
ELSE :new.ITM_NM
END);
END IF;
ELSIF deleting THEN H_TYP := 'D';
...
END IF;
END;
END;
If I login by SL01 result will always read in the last statement (ELSE ...). It should be execute the first statement.
I need a help for fixing this problem.
It looks like you are never setting H_INS_USR_ID to any value. I assume it is meant to the user for the incoming row? If that is the case, then
H_INS_USR_ID TMCI_SUB_ITEM_MASTER_R.INS_USR_ID%TYPE;
becomes
H_INS_USR_ID TMCI_SUB_ITEM_MASTER_R.INS_USR_ID%TYPE := :new.INS_USR_ID;
I am creating a trigger to add same SEQ.nextval numbers to two fields such as follows:
SITE_NUM SITE_NUM_COPY Site_Name
346 346 XYZ
347 347 ABC
348 348 DEF
Whenever a new row is added through an application I want the SITE_NUM and SITE_NUM_COPY will be auto generated through the trigger.
This is what I have put together:
create or replace trigger SITE_TRIGGER
before insert or update on STRATEGY_SITES for each row
begin
if updating then
if :new.SITE_NUM is null and :new.SITE_NUM_Copy is NULL then
:new.SITE_NUM := :old.SITE_NUM
and :old.SITE_NUM := :new.SITE_NUM_COPY;
end if;
end if;
if inserting then
:new.SITE_NUM := SITENUM_SEQ.nextval
and :new.SITE_NUM_COPY := SITENUM_SEQ.nextval;
end if;
end;
Getting the following error:
Error(7,31): PLS-00103: Encountered the symbol "=" when expecting one of the following:
. ( * # % & = - + ; < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like like2 like4 likec between || indicator multiset member submultiset
The symbol "* was inserted before "=" to continue.
The error is not very helpful but is stemming from you using and to, apparently, seperate two statements inside each if block. The statement terminator/separator is a semicolon.
It looks like you are trying to do this for the first one:
if updating then
if :new.SITE_NUM is null and :new.SITE_NUM_Copy is NULL then
:new.SITE_NUM := :old.SITE_NUM;
:old.SITE_NUM := :new.SITE_NUM_COPY; -- illegal
end if;
end if;
but you cannot change the :old values; it isn't clear what you expect to happen, ot least as the value assigning must be null. You may just want to remove that line.
And for the second part:
if inserting then
:new.SITE_NUM := SITENUM_SEQ.nextval;
:new.SITE_NUM_COPY := SITENUM_SEQ.currval;
end if;
I've changed the second assignment to use currval because you said you wanted the same value for both columns. If you call nextval for both assignments they will get different values simce the sequnce will increment twice.
I am creating trigger when Selisih column is equal to 0, then Status column become 'Partial'. If QtyInternalUse column is equal to QtyRequested, then Status column is Completed, else, it is Not Issued
CREATE OR REPLACE TRIGGER TG_STATUSINREQ
BEFORE UPDATE OR INSERT ON M_INTERNALREQUESTERLINE
FOR EACH ROW
BEGIN
IF (:new.Selisih <> 0 ) THEN
:new.Status := 'Partial';
ELSIF :new.QtyInternalUse := :new.QtyRequested THEN
:new.Status := 'Completed';
ELSE
:new.Status := 'Not Issued';
END IF;
END;
I've tried execute it and there's error that says
PLS-00103: Encountered the symbol "=" when expecting one of the
following:
. ( * # % & = - + < / > at in is mod remainder not rem then
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || indicator multiset member submultiset
The symbol "* was inserted before "=" to continue.
I've tried deleting : in = but still it won't work. How can I fix this?
REVISION
I have updated the logic and the := . The trigger was created and it's like this :
BEGIN
IF (:new.QtyInternalUse = 0 ) THEN
:new.Status := 'Not Issued';
ELSIF :new.QtyInternalUse = :new.QtyRequested THEN
:new.Status := 'Completed';
ELSE
:new.Status := 'Partial';
END IF;
END;
This should be pretty easy google-resolve. Still here you go.
ELSIF :new.QtyInternalUse := :new.QtyRequested THEN
You are trying to compare but using assignment operator[:=]. Use equals[=] in stead that will resolve your problem.
ELSIF :new.QtyInternalUse = :new.QtyRequested THEN
here is my code:
DECLARE
V_loop number(2); -------declare the loop times
begin
looptimes(V_loop); ------set the forcast times from parameter table
loop
IF V_loop > 0 ------forcast
THEN
IF to_char((sysdate+V_loop-7),'dd/mon/yy') not like To_chat((d.holiday_date),'dd/mon/yy')----------condition that perivous 'day' not holiday
then
insert into local_rm16(tni, lr, frmp, day, hh, volume)
SELECT TNI, LR, FRMP, sysdate+v_loop, HH, AVG(VOLUME)
FROM V_nem_rm16,DBP_holiday d
where to_char(day, 'Day') = to_char(sysdate+V_loop, 'Day')
group by day,hh, lr, frmp,tni
order by 1;
else
exit;
end if;
V_loop := V_loop -1;
ELSE
exit;
ENd if;
END loop;
end;
i dont know howto declare holiday_date in if conditions, can anyone help me, thx
You have written to_chat instead of to_char:
IF to_char((sysdate+V_loop-7),'dd/mon/yy') not like To_chat((d.holiday_date),'dd/mon/yy')
You can't use d before you defined it. It's defined in SELECT as an alias to DBP_holiday table, but you use it earlier in IF expression. You should think once again about your code, because you can't do it like this (maybe you should consider using cursor loop).
When attempting to compile I am getting the following errors
Error(16,8): PLS-00103: Encountered the symbol "SPROLLUPEXPENSEITEM"
when expecting one of the following: := . ( # % ; The symbol ":="
was substituted for "SPROLLUPEXPENSEITEM" to continue.
and
Error(17,15): PLS-00103: Encountered the symbol "=" when expecting one
of the following: . ( * # % & = - + < / > at in is mod remainder
not rem then <> or != or ~= >= <= <> and or like
like2 like4 likec between || multiset member submultiset
create or replace
TRIGGER tr_ExpenseItem_Rollup
AFTER DELETE OR UPDATE of ExpApprAmt
ON ExpenseItem
FOR EACH ROW
DECLARE
RollupAmt Number;
BlnResult Boolean;
BEGIN
IF DELETING THEN
RollupAmt := -1 * :Old.ExpApprAmt;
End If;
IF UPDATING Then
RollupAmt := :New.ExpApprAmt - :Old.ExpApprAmt;
End IF;
Call spRollUpExpenseItem(:New.ERNo,:New.ECNo,RollupAmt,BlnResult);
If BlnResult := TRUE
--Additional Logic Here
End IF;
END;
I'm a student and very new at this, so any help would be appreciated.
call isn't a keyword in PL/SQL and to run a stored procedure you just use its name. Remove call from before spRollUpExpenseItem:
create or replace
TRIGGER tr_ExpenseItem_Rollup
AFTER DELETE OR UPDATE of ExpApprAmt
ON ExpenseItem
FOR EACH ROW
DECLARE
RollupAmt Number;
BlnResult Boolean;
BEGIN
IF DELETING THEN
RollupAmt := -1 * :Old.ExpApprAmt;
End If;
IF UPDATING Then
RollupAmt := :New.ExpApprAmt - :Old.ExpApprAmt;
End IF;
spRollUpExpenseItem(:New.ERNo,:New.ECNo,RollupAmt,BlnResult);
If BlnResult = TRUE Then
--Additional Logic Here
End IF;
END;
I believe your problem is in the last if statement. You're missing Then and you're using := which is the assignment operator, you should use = instead.
If BlnResult = TRUE Then
or just
If BlnResult Then