Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So I'm trying to write a trigger that when something is inserted into the database if it is over a specific time set the row values to null
CREATE OR REPLACE TRIGGER hi
AFTER INSERT OR UPDATE OF CLASS_TIME ON class
FOR EACH ROW
BEGIN
IF (:NEW.CLASS_TIME < '09:00' )
OR (:NEW.CLASS_TIME > '18:00' )
THEN
RAISE_APPLICATION_ERROR(-20000, 'Due to low attendance no class cannot be scheduled at that time');
SET NEW.STAFFNO = NULL;
SET NEW.CLASS_DAY = NULL;
SET NEW.CLASS_TYPE = NULL;
SET NEW.ROOMNUM = NULL;
END IF;
END;
All that I have found online shows that what Ive got is correct but I get the error on the STAFFNO. Thanks in advance for any input.
First of all you have to decide:
either you want the insert or update to fail when it's being done at undesired time
or you want the insert or update to be processed, but with the columns set to null then.
You cannot have both.
In case you want to set the columns to NULL, this should be a BEFORE INSERT/UPDATE trigger, so the changed columns get written to the table. (In an AFTER INSERT/UPDATE trigger setting the fields to some value would not have any effect, becase they are not written.)
Then SET NEW.STAFFNO = NULL; is no valid PL/SQL, that would have to be :NEW.STAFFNO := NULL; instead.
CREATE OR REPLACE TRIGGER hi
BEFORE INSERT OR UPDATE OF class_time ON class
FOR EACH ROW
WHEN (new.class_time NOT BETWEEN '09:00' AND '18:00')
BEGIN
:new.staffno := null;
:new.class_day := null;
:new.class_type := null;
:new.roomnum := null;
END;
Related
This question already has answers here:
Oracle SQL Insert Trigger to Hash Password is not working (Issue with CHAR)
(3 answers)
Closed 1 year ago.
I am working on a requirement.
I have to apply trigger to mask data to a particular column in the database.
The table has 4 columns, firstName, lastName, userID, password. I want to write a trigger that masks the passsword column.
Here is the trigger, but its not working as expected.
CREATE OR REPLACE TRIGGER dmm_live.TRG_I_TUSER_PASSWORD_HASHING
AFTER INSERT OR UPDATE ON dmm_live.SampleHashPassword
FOR EACH ROW
DECLARE
/* Package :
* Author :
* Created :
* Description : Trigger
*
*/
vType VARCHAR2(1);
BEGIN
IF INSERTING THEN
vTYPE := 'I';
ELSIF UPDATING THEN
vType := 'U';
END IF;
IF INSERTING OR UPDATING THEN
INSERT INTO dmm_live.SampleHashPassword (password) values utl_i18n.STRING_TO_RAW(password, 'AL32UTF8');
--SET PASSWORD =utl_i18n.STRING_TO_RAW(PASSWORD, 'AL32UTF8');
END IF;
EXCEPTION WHEN OTHERS THEN
NULL;
Can anyone please help?
In a trigger you can set or change the values of a column in the updated table - that is done by referencing the column as a bind variable. Basically this is invoked during the dml process, so you wouldn't do a insert into the table (remember you're in the actual insert process).
I removed the unused lines of code.
One remark... WHEN OTHERS THEN NULL; is very scary. That means you don't care if anything goes wrong. I would want to see the error, log it and probably display an error in the application as well...
CREATE OR REPLACE TRIGGER dmm_live.TRG_I_TUSER_PASSWORD_HASHING
AFTER INSERT OR UPDATE ON SampleHashPassword
FOR EACH ROW
DECLARE
/* Package :
* Author :
* Created :
* Description : Trigger
*
*/
vType VARCHAR2(1);
BEGIN
:NEW.SampleHashPassword := utl_i18n.STRING_TO_RAW(password, 'AL32UTF8');
--SET PASSWORD =utl_i18n.STRING_TO_RAW(PASSWORD, 'AL32UTF8');
EXCEPTION WHEN OTHERS THEN
NULL;
END dmm_live.TRG_I_TUSER_PASSWORD_HASHING;
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
It should make a bank transaction. So i have a table called "transaction" and also an "account" table and a "withdraw" and "deposit". The procedure should create a row in the transaction table. It should call my function which looks if the person is certified. If the user isnt error should show of course. If the transaction has been made the new "saldo" (which is in the account table) of both accounts should be printed. This is what i have so far:
create or replace procedure do_transaction(
p_rownr in transaction.rownr%type,
p_pnr in transaction.pnr%type,
p_knr in transaction.knr%type,
p_date in transaction."date"%type)
as
not_certified exception;
begin
insert into transaction(rownr,pnr,knr,"date")
values(p_rownr,p_pnr,p_knr,p_date);
if user <> get_certification(p_pnr,p_knr) then
raise not_certified;
end if;
dbms_output.put_line('Pnr: '||''||p_pnr||''||'Current saldo: '||''||get_saldo(p_knr)); /*I also have a function which gets the saldo from the matching knr*/
commit;
exception
when not_certified then
raise_application_error(-20007,'Not certified!');
end;
The get certification function:
create or replace function get_certification(
p_pnr in bankcust.pnr%type,
p_knr in account.knr%type)
return varchar2
as
v_certification bankcust.pnr%type;
begin
select count(*)
into v_certification
from bankcust,account
where pnr = p_pnr
and knr = p_knr;
return v_certification;
exception
when no_data_found then
return -1;
end;
Any suggestions?
I am going to take a guess here as you did not actually state your problem. But that issue is your do_transaction procedure always results in the not certified exception. This is the result of the statement
if user <> get_certification(p_pnr,p_knr) then
This will always evaluate true. It compares the character representation of the result count function from get_certification to the current user (unless the user is presumably '1') thus always resulting in "raise not_certified;" being executed. Additionally, while not actually an exception but falls into the category of not doing unnecessary work; validate certification before inserting into transaction. So:
create or replace procedure do_transaction(
p_rownr in transaction.rownr%type,
p_pnr in transaction.pnr%type,
p_knr in transaction.knr%type,
p_date in transaction."date"%type)
as
not_certified exception;
begin
if get_certification(p_pnr,p_knr) = 0 then
raise not_certified;
end if;
insert into transaction(rownr,pnr,knr,"date")
values(p_rownr,p_pnr,p_knr,p_date);
dbms_output.put_line('Pnr: '||''||p_pnr||''||'Current saldo: '||''||get_saldo(p_knr)); /*I also have a function which gets the saldo from the matching knr*/
commit;
exception
when not_certified then
raise_application_error(-20007,'Not certified!');
end do_transaction;
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I'm trying to generate a trigger that if a column within a table is filled in with a specific set value e.g. i have a column named 'Volunteertype' which can only be assigned either 'staff' of 'student', if student is entered the trigger must nullify all columns relating to staff details within the volunteer table such as 'area of work', 'staffmanager' etc below is code i have tried to put together utilising the resources on the website however i'm having no luck.
CREATE TRIGGER trg_voltype
ON Volunteer
AFTER INSERT
AS
IF EXISTS (SELECT NULL FROM inserted i WHERE VolunteerType = 'student')
FOR EACH ROW BEGIN;
UPDATE v
SET Area_of_work = NULL
SET StaffManagerName = NULL
SET StaffManagerEmail = NULL
SET StaffManagerPhone = NULL
FROM Volunteer v
JOIN inserted i ON v.Volunteer_id = i.Volunteer_id
WHERE v.VolunteerType = 'student';
END;
However when this is run within the Oracle environment an error is produced ORA-04071: missing BEFORE, AFTER or INSTEAD OF keyword. when i attempt to shift the 'AFTER INSERT' to before the keyword i get an 'invalid trigger' error
Is anyone able to assist and inform me if the code itself is correct/ incorrect and how i should go about amending the code, thanks in advance and have a wonderful end to the year thanks!
Your trigger should be like :
CREATE OR REPLACE TRIGGER trg_voltype
BEFORE INSERT ON volunteer
FOR EACH ROW
BEGIN
if :new.Volunteertype = 'STUDENT'
then
:new.Area_of_work := NULL;
:new.StaffManagerName := NULL;
:new.StaffManagerEmail := NULL;
:new.StaffManagerPhone := NULL ;
end if;
END;
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
CONSTRAINT (Movie.Date – person.DateOfBirth >= Movie.MinAge)
I am trying to use triggers for this constraint, I am not sure how to use triggers when you are comparing different data from different tables.
Something like this.. I didn't test it!!
CREATE OR REPLACE TRIGGER check_movie_parent_rating
BEFORE INSERT OR UPDATE OF DateOfBirth ON Person
REFERENCING NEW AS n
FOR EACH ROW
DECLARE
v_allowed VARCHAR2(1);
BEGIN
BEGIN
SELECT CASE WHEN (Movie.Date - person.DateOfBirth >= Movie.MinAge)
THEN 'Y'
ELSE 'N'
END As Allowed
INTO v_allowed
FROM Movie , Person
WHERE Movie.id = :n.movieId
AND Person.movieId = Movie.id
AND Person.id = :n.id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_allowed := NULL;
END;
IF v_allowed IS NULL THEN
Raise_application_error(-20202, 'Movie Detail not available in parent');
ELSIF v_allowed = 'N' THEN
Raise_application_error(-20201, 'Movie Restricted for User');
END IF;
END;
/
Here is a solution that will avoid the mutating table error that arises when you select from a table within a row level trigger defined against the same table.
You should check the constraint whenever any involved table is changed.
Ideally, there should also be serialisation locks at within the trigger to ensure transactions executing concurrently do not alter the data in such a way as to break the constraint. This can be achieved by using modules within the supplied DBMS_LOCK package.
CREATE OR REPLACE TRIGGER Movie_Check_Age
AFTER INSERT OR UPDATE OF <Join_Columns>, Date, MinAge ON Movie
FOR EACH ROW
DECLARE
CURSOR csrPersons
IS
SELECT NULL
FROM Person p
WHERE p.<Join_Columns> = :new.<Join_Columns>
AND (Months_Between(:new.Date, p.DateOfBirth) / 12) < :new.MinAge;
rPerson csrPersons%ROWTYPE;
BEGIN
OPEN csrPersons;
FETCH csrPersons INTO rPerson;
IF csrPersons%FOUND THEN
CLOSE csrPersons;
Raise_Application_Error(-20001, 'Person too young to see movie');
ELSE
CLOSE csrPersons;
END IF;
END;
/
CREATE OR REPLACE TRIGGER Person_Check_Age
AFTER INSERT OR UPDATE OF <Join_Columns>, DateOfBirth ON Person
FOR EACH ROW
DECLARE
CURSOR csrMovies
IS
SELECT NULL
FROM Movie m
WHERE m.<Join_Columns> = :new.<Join_Columns>
WHERE (Months_Between(m.Date, :new.DateOfBirth) / 12) < m.MinAge;
rMovie csrMovies%ROWTYPE;
BEGIN
OPEN csrMovies;
FETCH csrMovies INTO rMovie;
IF csrMovies%FOUND THEN
CLOSE csrMovies;
Raise_Application_Error(-20001, 'Person too young to see movie');
ELSE
CLOSE csrMovies;
END IF;
END;
/
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have a query as shown below:
TRUNCATE TABLE DNARTLOAD;
COMMIT;
.... <Cursor here> .... <do something>.....
tmp_future_phaseA := substr(tmp_phases,1,1);
tmp_future_phaseB := substr(tmp_phases,2,1);
tmp_future_phaseC := substr(tmp_phases,3,1);
INSERT INTO DNARTLOAD (LOADNAME,KVARATING,PHASE,FULLPHASE) VALUES
(tmp_load_name, tmp_kvarating, tmp_future_phaseA, tmp_phase);
The problem is that the query fails to insert tmp_phases correctly every time. What I'm doing is taking the substring of temp phases (which is never null) and assigning the first, second, and third character to another set of varchar variables. Once they are assigned, I insert the data into a table and commit. The problem is it doesn't work all the time. It will ALWAYS fill tmp_future_phaseA, B, and C with a character, but when I insert the tmp_phase it will sometimes populate null and sometimes populate the values.
Example Data:
tmp_phase = 'ABC'
tmp_futurephaseA = 'A'
tmp_futurephaseB = 'B'
tmp_futurephaseC = 'C'
Sometimes I'll get the following:
A 'ABC'
B 'ABC'
C 'ABC'
Other times during the same plsql I'll get the following:
A NULL
B NULL
C NULL
EDIT: Added for question:
LOOP
tmp_future_phaseA := NULL;
tmp_future_phaseB := NULL;
tmp_future_phaseC := NULL;
tmp_phases := NULL;
FETCH C3 INTO tmp_load_name, tmp_kvarating, tmp_phases;
EXIT WHEN C3%NOTFOUND;
IF LENGTH(tmp_phases) = 3 THEN
tmp_kvarating := tmp_kvarating / 3;
END IF;
IF LENGTH(tmp_phases) = 2 THEN
tmp_kvarating := tmp_kvarating /2;
END IF;
tmp_future_phaseA := substr(tmp_phases,1,1);
tmp_future_phaseB := substr(tmp_phases,2,1);
tmp_future_phaseC := substr(tmp_phases,3,1);
IF tmp_future_phaseA IS NOT NULL THEN
INSERT INTO DNARTLOAD (LOADNAME,KVARATING,PHASE) VALUES (tmp_load_name, tmp_kvarating, tmp_future_phaseA);
END IF;
IF tmp_future_phaseB IS NOT NULL THEN
INSERT INTO DNARTLOAD (LOADNAME,KVARATING,PHASE) VALUES (tmp_load_name, tmp_kvarating, tmp_future_phaseB);
END IF;
IF tmp_future_phaseC IS NOT NULL THEN
INSERT INTO DNARTLOAD (LOADNAME,KVARATING,PHASE) VALUES (tmp_load_name, tmp_kvarating, tmp_future_phaseC);
END IF;
"Sometimes I'll get the following: ... Other times during the same
plsql I'll get the following:"
Sometimes your program works, sometimes it doesn't. This means you have a data problem.
More accurately, you have written a program which caters correctly for data in some states but not in others. There's absolutely no way we're going to be able to diagnose that.
So, what you need to do is debug your code. If you have a proper IDE that should offer you a debugging facility. Otherwise you will need to use something like DBMS_OUTPUT to display the input for each trip round the loop and the subsequent outcome, so that you can understand which values your program isn't handling correctly.