How do I check that when a user enters their date of birth into my database that they are 12 and over?
I am using SQL plus.
Right now I have somthing like this:
create table test(dateofbirth date not null,
CONSTRAINT dateofbirth_ck CHECK(TO_CHAR(dateofbirth, 'YYYY-MM-DD') <= '2002-02-09')
);
The problem with this is that it does not update every day, so the '2002-02-09' should be changed every day.
I know what to do but I'm not sure how to execute it. I want to get the 'Dateofbirth' & sysdate - 12 years and if user is above 12 it will let them.
Oracle won't you let use sysdate in a check constraint (or other functions whose return value is not constant over time).
You can, however, write a trigger that implements the same logic:
create or replace trigger trg_mytable_dateofbirth
before insert or update on mytable
for each row
begin
if :new.dateofbirth > add_months(sysdate, -12 * 12)
then
raise_application_error( -20001,
'invalid date of birth - current value:'
|| to_char(:new.dateofbirth, 'yyyy-mm-dd')
|| ', limit as of today:'
|| to_char(add_months(sysdate, -12 * 12), 'yyyy-mm-dd')
);
end if;
end;
/
Demo on DB Fiddle:
insert into mytable(dateofbirth) values (date'2000-01-01')
-- 1 rows affected
insert into mytable(dateofbirth) values (date'2010-01-01')
-- ORA-20001: invalid date of birth - current value:2010-01-01, limit as of today:2008-02-10
-- ORA-06512: at "FIDDLE_MYQIVTFXTMKGROKMNOGB.TRG_MYTABLE_DATEOFBIRTH", line 4
-- ORA-04088: error during execution of trigger 'FIDDLE_MYQIVTFXTMKGROKMNOGB.TRG_MYTABLE_DATEOFBIRTH'
Related
I have used this trigger:
CREATE OR REPLACE TRIGGER trg_chk_future
BEFORE INSERT ON your_table
FOR EACH ROW
BEGIN
IF( :new.date_time < sysdate )
THEN
RAISE_APPLICATION_ERROR( -20001, 'date_time must be in the future' );
END IF;
END;
However the current date comes up as an error when entered such as 12/12/2021 (today date) but 13/12/21 and any date after the today date works.
Any ideas what's wrong.
If you really inserted values you wrote in the question, who-knows-what you really inserted. Because, those are strings, not date values. Therefore, Oracle tried to convert them to valid DATE datatype values and - according to what you said - failed.
It means that you should actually insert DATE values, like the following example shows (trigger is exactly the same as you made it):
SQL> create table your_table (date_time date);
Table created.
SQL> CREATE OR REPLACE TRIGGER trg_chk_future
2 BEFORE INSERT ON your_table
3 FOR EACH ROW
4 BEGIN
5 IF( :new.date_time < sysdate )
6 THEN
7 RAISE_APPLICATION_ERROR( -20001, 'date_time must be in the future' );
8 END IF;
9 END;
10 /
Trigger created.
Testing: truncated sysdate is set to midnight (which was in the past, and thus rejected):
SQL> insert into your_table values (trunc(sysdate));
insert into your_table values (trunc(sysdate))
*
ERROR at line 1:
ORA-20001: date_time must be in the future
ORA-06512: at "SCOTT.TRG_CHK_FUTURE", line 4
ORA-04088: error during execution of trigger 'SCOTT.TRG_CHK_FUTURE'
May this year, also in the past:
SQL> insert into your_table values (date '2021-05-25');
insert into your_table values (date '2021-05-25')
*
ERROR at line 1:
ORA-20001: date_time must be in the future
ORA-06512: at "SCOTT.TRG_CHK_FUTURE", line 4
ORA-04088: error during execution of trigger 'SCOTT.TRG_CHK_FUTURE'
This is in the future, so it is accepted:
SQL> insert into your_table values (date '2021-12-26');
1 row created.
SQL>
As of
the current date comes up as an error when entered such as 12/12/2021 (today date)
Maybe you meant to say
IF( :new.date_time < trunc(sysdate))
which truncates sysdate to midnight today. In that case, today's date is also accepted:
SQL> CREATE OR REPLACE TRIGGER trg_chk_future
2 BEFORE INSERT ON your_table
3 FOR EACH ROW
4 BEGIN
5 IF( :new.date_time < trunc(sysdate))
6 THEN
7 RAISE_APPLICATION_ERROR( -20001, 'date_time must be in the future' );
8 END IF;
9 END;
10 /
Trigger created.
SQL> insert into your_table values (date '2021-12-12');
1 row created.
SQL>
I want to put a constraint on a date of birth field for one of my db tables. Essentially I want to ensure pat_dob_dt is at least 16 years ago (from current date). I am using PostgreSQL 8.4.20 and used here for guidance:
CREATE OR REPLACE FUNCTION patient_dob_in_past()
RETURNS TRIGGER AS $$
BEGIN
-- check pat_dob_dt is in past --
IF ( NEW.pat_dob_dt > current_date - interval '16 years' ) THEN
RAISE EXCEPTION '% must be 16 years in past', NEW.pat_dob_dt
END IF;
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE OR REPLACE TRIGGER patient_dob_in_past BEFORE UPDATE OR INSERT
ON patients FOR EACH ROW EXECUTE PROCEDURE patient_dob_in_past();
Unfortunately I am met with the following error
ERROR: syntax error at or near "END" at character 14
QUERY: SELECT $1 END IF
CONTEXT: SQL statement in PL/PgSQL function "patient_dob_in_past" near line 4
LINE 1: SELECT $1 END IF
Not sure where I am going wrong since I am following the psql docs for 8.4
EDIT
Semicolon fixeds function issue. I also get an error for my trigger
ERROR: syntax error at or near "TRIGGER" at character 19
LINE 1: CREATE OR REPLACE TRIGGER patient_dob_in_past BEFORE UPDATE ...
try:
CREATE OR REPLACE FUNCTION patient_dob_in_past()
RETURNS TRIGGER AS $$
BEGIN
-- check pat_dob_dt is in past --
IF ( NEW.pat_dob_dt > current_date - interval '16 years' ) THEN
RAISE EXCEPTION '% must be 16 years in past', NEW.pat_dob_dt;
END IF;
RETURN NEW;
END;
$$ language 'plpgsql';
also https://www.postgresql.org/docs/current/static/sql-createtrigger.html
CREATE OR REPLACE TRIGGER
will fail as it does not work with OR REPLACE - use just CREATE TRIGGER instead
also why not CHECK constraints? eg:
t=# create table q2(t timestamptz check (t < now() - '16 years'::interval));
CREATE TABLE
t=# insert into q2 select now();
ERROR: new row for relation "q2" violates check constraint "q2_t_check"
DETAIL: Failing row contains (2017-10-10 11:41:01.062535+00).
t=# insert into q2 select now() - '16 years'::interval;
ERROR: new row for relation "q2" violates check constraint "q2_t_check"
DETAIL: Failing row contains (2001-10-10 11:41:13.031769+00).
t=# insert into q2 select now() - '16 years'::interval -'1 second'::interval;
INSERT 0 1
update
In case of existing previous values that do not match check constraint - you can delay check with NOT VALID, eg:
t=# create table q2(t timestamptz);
CREATE TABLE
t=# insert into q2 select now();
INSERT 0 1
t=# alter table q2 add constraint q2c check (t < (now() - '16 years'::interval)) not valid;
ALTER TABLE
t=# insert into q2 select now();
ERROR: new row for relation "q2" violates check constraint "q2c"
DETAIL: Failing row contains (2017-10-10 11:56:02.705578+00).
You missed semicolon at the end of the line.
RAISE EXCEPTION '% must be 16 years in past', NEW.pat_dob_dt;
Hi guys I have two triggers I am meant to be be creating but I am getting compilation errors on both
this first is supposed to record evaluations of 0 to an audit table and the second is supposed to prevent the deletion of entries in which the date is less than todays date.
SQL> CREATE TABLE EVALUATION_AUDIT
2 (C_NAME VARCHAR (15), CO_ID NUMBER(7), E_DATE DATE,
3 V_ID NUMBER (7), C_EVALUATION NUMBER(1));
Table created.
SQL> CREATE OR REPLACE TRIGGER ZERO_EVAL
2 BEFORE INSERT OR UPDATE OF C_EVALUATION ON CUSTOMER_EVENT
3 FOR EACH ROW
4 WHEN (NEW.C_EVALUATION = 0)
5 BEGIN
6 SELECT C_NAME, CO_ID, E_DATE, V_ID, C_EVALUATION
7 FROM CUSTOMER_EVENT CE, CUSTOMER C, EVENT E
8 WHERE CE.C_ID = C.C_ID
9 AND CE.EVENT_ID = E.EVENT_ID
10 AND C_EVALUATION = NEW.C_EVALUATION;
11 INSERT INTO EVALUATION AUDIT
12 VALUES (:NEW.C_NAME, :NEW.CO_ID, :NEW.E_DATE, :NEW.V_ID, :NEW.C_EVALUATION);
13 END;
14 /
Warning: Trigger created with compilation errors.
SQL> CREATE OR REPLACE TRIGGER PASTEVENTS
2 BEFORE DELETE
3 ON EVENT
4 FOR EACH ROW
5 BEGIN
6 IF :OLD.E_DATE =< SYSDATE
7 THEN RAISE_APPLICATION_ERROR (-20002, 'CAN NOT DELETE PAST EVENT RECORDS');
8
9 END IF;
10 END;
11 /
Warning: Trigger created with compilation errors.
As Justin said, when you get created with compilation errors for any stored PL/SQL, type show errors, or you can query the user_errors table to see all outstanding errors on your objects.
From a quick scan, the first trigger is missing a colon when you reference NEW.C_EVALUATION in the select:
AND C_EVALUATION = :NEW.C_EVALUATION;
You need to select into something, though I'm not sure if it's necessary here as you have the values from the :NEW psuedorecord; not sure why you're selecting at all?
And the second has an incorrect operator, =< instead of <=:
IF :OLD.E_DATE <= SYSDATE
It's generally a good idea to prefix column names with the table alias to avoid ambiguity, e.g. SELECT C.C_NAME, ... if that column comes from the CUSTOMER table, etc. You could have another error in there is you have the same column on multiple tables. And it's good practise to list the column names in your INSERT too, i.e. INSERT INTO EVALUATION_AUDIT (C_NAME, ...) VALUES (...). With the missing underscore that #Dba spotted!
In your first trigger code you don't need to SELECT from the tables as you are just inserting the values from the table CUSTOMET_EVENT to EVALUATION_AUDIT. Also you have missed and underscore _ in table_name in EVALUATION_AUDIT in line 11.
CREATE OR REPLACE TRIGGER zero_eval
BEFORE INSERT OR UPDATE OF c_evaluation ON customer_event
FOR EACH ROW
WHEN (NEW.c_evaluation = 0)
BEGIN
INSERT INTO evaluation_audit(c_name, co_id, e_date, v_id, c_evaluation)
VALUES (:NEW.c_name, :NEW.co_id, :NEW.e_date, :NEW.v_id, :NEW.c_evaluation);
END;
/
In Your second code, it should be <= instead of =<
CREATE OR REPLACE TRIGGER pastevents
BEFORE DELETE
ON event
FOR EACH ROW
BEGIN
IF :OLD.e_date <= SYSDATE THEN
raise_application_error (-20002, 'CAN NOT DELETE PAST EVENT RECORDS');
END IF;
END;
/
I have two tables:
Assessment and Assessment_Announcement
CREATE TABLE "ASSESSMENT"
( "ASSESSMENT_NAME" VARCHAR2(50) NOT NULL ENABLE,
"DEADLINE_DATE" DATE NOT NULL ENABLE,
CONSTRAINT "ASSESSMENT_PK" PRIMARY KEY ("ASSESSMENT_NAME") ENABLE
)
CREATE TABLE "ASSESSMENT_ANNOUNCEMENT"
( "ASSESSMENT_NAME" VARCHAR2(50) NOT NULL ENABLE,
"DEADLINE_DATE" DATE NOT NULL ENABLE,
"ATTENTION" VARCHAR2(500) NOT NULL ENABLE,
CONSTRAINT "ASSESSMENT_ANNOUNCEMENT_PK" PRIMARY KEY ("ASSESSMENT_NAME") ENABLE
)
I am looking at implementing a trigger which updates to the 'ASSESSMENT_ANNOUNCEMENT' table when the date in the DEADLINE_DATE column on the ASSESSMENT table is within 7 days. The data might have been stored for 14 days, but when it is within 7 days of the deadline - it triggers. This shouldn't trigger on insert unless the insert date is within 7 days of the deadline.
So far I have the following code:
CREATE OR REPLACE TRIGGER "TEST"
AFTER INSERT ON ASSESSMENT
FOR EACH ROW
BEGIN
insert into ASSESSMENT_ANNOUNCEMENT(ASSESSMENT_NAME, DEADLINE_DATE, ATTENTION)
values (:new.ASSESSMENT_NAME, :new.DEADLINE_DATE, 'DEADLINE IS 7 DAYS OR LESS');
WHERE DEADLINE_DATE >= (SYSDATE) - 7
Any help and guidance would be greatly appreciated!
Thanks!
It sounds like you want
BEGIN
IF :new.deadline_date >= sysdate + 7
THEN
INSERT INTO assessment_announcement( assessment_name, deadline_date, attention )
VALUES( :new.assessment_name, :new.deadline_date, 'Deadline is 7 days or less' );
END IF;
END;
Note that an Oracle DATE always contains a day component and a time component. So sysdate + 7 returns exactly 24*7 = 168 hours ago. If it is currently 4:00 PM on Feb 26, it would return 4:00 PM on March 5. If you want the trigger to insert a row in assessment_announcement if the deadline_date is any time on March 5, you'd need trunc(sysdate) + 7.
I don't believe you can accomplish what you want with a trigger as you have no guarantee that the table will be updated within the timeframe you want. Instead you should be looking to run a stored procedure to do this that can be scheduled on an appropriate interval; say every day or every 12 hours. I've done this with MSSQL and not oracle, but this article should help you get started on your way.
The PL-SQL BLock you want to schedule is your query above. You could modify it to be
insert into ASSESSMENT_ANNOUNCEMENT(ASSESSMENT_NAME, DEADLINE_DATE, ATTENTION)
Select ASSESSMENT_NAME, DEADLINE_DATE, 'Deadline is 7 days or less'
FROM ASSESSMENT
WHERE DEADLINE_DATE >= (SYSDATE) - 7
I am new to triggers in Oracle. I created an EVENT table with this syntax:
CREATE TABLE Event
(event_id NUMBER (3) NOT NULL,
event_date DATE NOT NULL,
venue_id NUMBER (2) NOT NULL,
concert_id NUMBER (3) NOT NULL
);
I want to create a trigger to ensure that concerts cannot run during the month of August. I tried the following code to create the trigger. The trigger was created successfully but after inserting a date with the month of August, it was inserted. This is not suppose to be.
CREATE OR REPLACE TRIGGER check_date
BEFORE INSERT ON event
DECLARE
event_date date;
BEGIN
IF (to_char(event_date, 'mm') = 8) THEN
raise_application_error(-20000, 'Concerts cannot be run during August');
END IF;
END;
First, the trigger needs to be a row-level trigger not a statement-level trigger. You want the trigger to be fired for every row that is inserted not just once for every statement. Declaring the trigger a row-level trigger allows you to see the data for each row that is being inserted.
Second, you don't want to declare a local variable event_date. You want to look at :new.event_date which is the event_date for the row that is being inserted.
If I put those two together
CREATE OR REPLACE TRIGGER check_date
BEFORE INSERT ON event
FOR EACH ROW
BEGIN
IF (to_char(:new.event_date, 'mm') = 8) THEN
raise_application_error(-20000, 'Concerts cannot be run during August');
END IF;
END;
then you'll get the behavior you want
SQL> insert into event values( 1, date '2012-08-01', 1, 1 );
insert into event values( 1, date '2012-08-01', 1, 1 )
*
ERROR at line 1:
ORA-20000: Concerts cannot be run during August
ORA-06512: at "SCOTT.CHECK_DATE", line 3
ORA-04088: error during execution of trigger 'SCOTT.CHECK_DATE'
As a general matter of cleanliness, you also want to compare strings with strings and numbers with numbers. So you would want either
to_number( to_char(:new.event_date, 'mm') ) = 8
or
to_char(:new.event_date, 'fmmm') = '8'
or
to_char(:new.event_date, 'mm') = '08'
change:
IF (to_char(event_date, 'mm') = 8) THEN
to:
IF (to_char(event_date, 'mm') = '08') THEN
You're comparing between string and number.