As sysdate cannot be used in check constraint, tried to a trigger to fulfill the purpose.
But its showing " Warning: Trigger created with compilation errors."
I am posting my syntax below. I am using Oracle 10g database.
create table birth
(name varchar2(30), DOB date);
insert into birth values ('Ravi', sysdate+1 );
1 row inserted.
Now technically this is wrong. To prevent this I an creating a trigger
create or replace trigger birth_trigger
before insert or update of dob on birth
for each row
begin
if (dob >=sysdate)
then
raise_application_error (-20501, 'DOB cannot be greater than sysdate');
end if;
end;
Now here I am getting the "Warning: Trigger created with compilation errors."
Not been able to resolve the problem.
Please help.
Your problem stems from the fact that you are attempting to reference the "dob" column incorrectly. If you execute, "show errors" , you should see the message, "[Error] PLS-00201 (7: 8): PLS-00201: identifier 'DOB' must be declared". You need to preface the column with the :new prefix (default) to access the record's values.
create or replace trigger birth_trigger
before insert or update of dob on birth
for each row
begin
if ( :new.dob >=sysdate)
then
raise_application_error (-20501, 'DOB cannot be greater than sysdate');
end if;
end;
I would recommend using an IDE to do PL/SQL development, such as Oracle free SQLDeveloper. Also, read the Oracle Documenation on triggers.
use the following code
create or replace trigger birth_trigger
before insert or update of dob on birth
referencing old as old new as new
for each row
begin
if (
trunc ( to_date(:new.dob, 'DD/MM/YYYY' )) >= trunc (to_date(sysdate,'DD/MM/YYYY' ))
)
then
raise_application_error (-20501, 'DOB cannot be greater than sysdate');
end if;
end;
in code i have used new and old keywords for accessing the new values inserted in the birth table.
Related
I am new to PL/SQL and I have an issue regarding a trigger I am trying to implement.
The triggers purpose is to check a monetary value before it's inserted into the table to see if someone made a mistake during inserting. If they have, they will be given a message stating the value is incorrect. The values are in the billions so for now I am just checking if the value entered is above 10000 or not.
The trigger I currently have is;
CREATE TRIGGER Check_Value
BEFORE INSERT OR UPDATE OF "Potential Annual Value By 2026" ON AIPOTENTIALVALUEFORHEALTHCARE
BEGIN
IF (NEW."Potential Annual Value By 2026" < 10000.00) THEN
DBMS_OUTPUT.put_line('Value typed was incorrect');
ELSIF (NEW."Potential Annual Value By 2026" >= 10000.00) THEN
INSERT INTO AIPOTENTIALVALUEFORHEALTHCARE VALUES(NEW.ValueID, NEW.ApplicationID, NEW."Application Name", NEW.KeyDriverForAdoptionID, NEW."KeyDriverDescription", NEW."Potential Annual Value By 2026");
END IF;
END;
This will not work due to an error:
PLS-00201: identifier NEW.'Potential Annual Value By 2026' must be declared
My guess is that I have set the trigger incorrectly and that it doesn't know which value to check when it runs the trigger. From some research, I tried to use .NEW to pass the values of the statement into the trigger however I am not sure if this is the correct implementation.
I had tried the method already posted;
CREATE TRIGGER Check_Value
BEFORE INSERT OR UPDATE OF "Potential Annual Value By 2026" ON AIPOTENTIALVALUEFORHEALTHCARE
BEGIN
IF (:NEW."Potential Annual Value By 2026" < 10000.00) THEN
DBMS_OUTPUT.put_line('Value typed was incorrect');
ELSIF (:NEW."Potential Annual Value By 2026" >= 10000.00) THEN
INSERT INTO AIPOTENTIALVALUEFORHEALTHCARE VALUES
(:NEW.ValueID, :NEW.ApplicationID, :NEW."Application Name",
:NEW.KeyDriverForAdoptionID, :NEW."KeyDriverDescription",
:NEW."Potential Annual Value By 2026");
END IF;
END;
and recieved a different error:
ORA-04082: NEW or OLD references not allowed in table level triggers
04082. 00000 - "NEW or OLD references not allowed in table level triggers"
*Cause: The trigger is accessing "new" or "old" values in a table trigger.
*Action: Remove any new or old references.
If this error is stating I can't use NEW references in a table level trigger, how would I be able to verify the contents of the insert statement before it is committed?
You are missing colons before the NEW keywords and the FOR EACH ROW clause. Also you do not need to (and must not) re-issue the INSERT within the trigger, it will happen anyway (if no error is raised):
CREATE TRIGGER Check_Value
BEFORE INSERT OR UPDATE OF "Potential Annual Value By 2026" ON AIPOTENTIALVALUEFORHEALTHCARE
FOR EACH ROW
BEGIN
IF (:NEW."Potential Annual Value By 2026" < 10000.00) THEN
RAISE_APPLICATION_ERROR(-20001, 'Value typed was incorrect');
END IF;
END;
I'm sure this is just a training example, but DBMS_OUTPUT.PUT_LINE is not a suitable method for raising errors to users as its output can only be seen when using develpper tools like SQL Developer. Use RAISE_APPLICATION_ERROR. Also it doesn't actually raise an exception, so it won't prevent the insert at all.
In fact, this check might be better done with a CHECK constraint - assuming the column value must never be under 10000:
ALTER TABLE AIPOTENTIALVALUEFORHEALTHCARE
ADD CONSTRAINT AIPOTENTIALVALUEFORHEALTHCARE_CHK_VALUE
CHECK ("Potential Annual Value By 2026" >= 10000);
Oracle APEX. I want to create trigger: if user deletes a row where ENDDATE is null the row won't be deleted overwise it will. This is my script:
CREATE OR REPLACE TRIGGER CHECK_NOT_NULL_
BEFORE DELETE ON CAREER
FOR EACH ROW
BEGIN
IF(OLD.ENDDATE IS NULL)
INSERT INTO CAREER VALUES (OLD.JOBNO, OLD.EMPNO, OLD.STARTDATE, OLD.ENDDATE);
END IF;
END CHECK_NOT_NULL_;
But I have ORA-24344 error. Can you explain why and what should I do to fix it?
Your trigger attempts to re-insert the row if the END_DATE is null. This won't work (you'll get the notorious mutating table error). But anyway, if you want to prevent deletion of the row it's simpler and clearer to simply do that:
CREATE OR REPLACE TRIGGER CHECK_NOT_NULL_
BEFORE DELETE ON CAREER
FOR EACH ROW
BEGIN
IF :OLD.ENDDATE IS NULL THEN
raise_application_error(-20000, 'Cannot delete a row when ENDDATE is null');
END IF;
END CHECK_NOT_NULL_;
This fails the action and tells the user why their action was refused. Silently undoing a user's action is bad practice, because it's mystifying, and mystified users are unhappy and often angry users.
Precede all olds with a colon :, i.e.
CREATE OR REPLACE TRIGGER CHECK_NOT_NULL_
BEFORE DELETE ON CAREER
FOR EACH ROW
BEGIN
IF(:OLD.ENDDATE IS NULL)
INSERT INTO CAREER VALUES (:OLD.JOBNO, :OLD.EMPNO, :OLD.STARTDATE, :OLD.ENDDATE);
END IF;
END CHECK_NOT_NULL_;
Also, I'd suggest you to name all columns you're inserting into, e.g.
insert into career (jobno, empno, startdate, enddate)
values (:old.jobno, :old.empno, :old.startdate, :old.enddate);
I'm going to create a trigger to audit a table. Suppose my table define as below.
COUNTRY_ID NOT NULL CHAR(2)
COUNTRY_NAME VARCHAR2(40)
REGION_ID NUMBER
and my log table created as below.
create table country_log(
username varchar2(10),
transaction_date date,
new_value varchar(20),
old_value varchar(20)
)
My half completed trigger would be like below.
CREATE OR REPLACE TRIGGER tr_countryTable
AFTER UPDATE ON COUNTRIES
FOR EACH ROW
BEGIN
insert into country_log (username,transaction_date,new_value,old_value ) values (USER, sysdate,**:New, :Old** );
END;
/
I need to know instead of comparing each column value in :old and :new, how to get exactly updated column's new and old values.
In an UPDATE trigger, a column name can be specified with an UPDATING predicate to determine if the named column is being updated. Let's define a trigger as the following:
CREATE OR REPLACE TRIGGER tr_countryTable
AFTER UPDATE ON COUNTRIES
FOR EACH ROW
BEGIN
IF UPDATING ('COUNTRY_NAME') THEN
-- :new.COUNTRY_NAME is new value
-- :old.COUNTRY_NAME is old value
END IF;
IF UPDATING ('REGION_ID') THEN
-- :new.REGION_ID is new value
-- :old.REGION_ID is old value
END IF;
END;
/
Oracle 11g triggers documentation
I have a column 'patient_dob' in 'patient' table. Now I want to create a trigger in oracle database so that patient cannot set future date as their birth date. So I ave write the following query:
create or replace trigger test_trigger
before insert
on employees
for each row
BEGIN
IF patient_dob > sysdate
THEN
RAISE_APPLICATION_ERROR(-20950, 'date error');
END IF;
END;
but the code is not working. Can anyone tell me how to create a trigger to perform the above functionality?
Thanks
Try using new to identify the column:
create or replace trigger test_trigger
before insert
on employees
for each row
BEGIN
IF :new.patient_dob > sysdate THEN
-------^
RAISE_APPLICATION_ERROR(-20950, 'date error');
END IF;
END;
I'm very new for trigger, now this what i was trying. I've two tables INSERTED and ORDER_INFO, both have the same column name ORDER_ID, ORDER_DATE. I've scenario, where client will be placing his/her order then, order information will be stored into INSERTED table, then by using this trigger, it'll insert into another table ORDER_INFO after satisfying the condition, which has been written.
create trigger tri_check
AFTER INSERT ON inserted FOR EACH ROW
DECLARE
v_date DATE;
BEGIN
SELECT order_date INTO v_date FROM inserted;
if (v_date)< (sysdate + 2) then
raiserror('You cannot take an order to be delivered less than 2 days from now',16, 1);
else
INSERT INTO orders_info
( order_id,order_date)
VALUES
(:new.order_id,v_date);
end if;
end;
But, when i'm executing the above trigger, then i'm getting this error.
ERROR at line 8: PL/SQL: SQL Statement ignored
6. SELECT order_date INTO v_date FROM inserted;
7. if (v_date)< (sysdate + 2) then
8. raiserror('You cannot take an order to be delivered less than 2 days from now',16, 1);
9. else
10. INSERT INTO orders_info
EDIT
Now, i made the same structure table into SYSTEM user, and got the same error. Table or View does not exist
Need help !! Thanks in advance !!
The message seems to indicate a problem with the 'raiserror' procedure. I'm not familiar with such a procedure in standard PL/SQL - did you mean RAISE_APPLICATION_ERROR? However, and perhaps more to the point, when using a trigger there's no need to do a SELECT from the table. All the data being inserted is available to the trigger. I suggest changing your trigger to be something like the following:
create trigger tri_check
AFTER INSERT ON inserted
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
if :new.ORDER_DATE < sysdate + INTERVAL '2' DAY then
RAISE_APPLICATION_ERROR(-20000, 'You cannot take an order to be delivered less than 2 days from now');
else
INSERT INTO orders_info
(order_id, order_date)
VALUES
(:new.order_id, :new.ORDER_DATE);
end if;
end TRI_CHECK;
Share and enjoy.
You can just use the :NEW and :OLD values instead of your select:
CREATE TRIGGER tri_check
AFTER INSERT
ON inserted
FOR EACH ROW
DECLARE
BEGIN
IF :new.order_date < (SYSDATE + 2)
THEN
raiserror (
'You cannot take an order to be delivered less than 2 days from now',
16,
1);
ELSE
INSERT INTO orders_info (order_id, order_date)
VALUES (:new.order_id, :new.order_date);
END IF;
END;
What is your raiserror procedure? Do you have access permissions granted on it?
Hope it helps...
EDIT:
OK, from your error, and the error you posted on #Bob Jarvis' answer, you might not have INSERT privilege on the ORDERS_INFO table. You also should check your permissions on the INSERTED table too.
Check your permissions with your DBA.
If raiserror is not a defined procedure or you don't have access to it then use the RAISE_APPLICATION_ERROR method for raising an error as Bob suggests.