Reputation: 337
I want to add a constraint on table to prevent the insertion/update of record based on some criteria.
More specifically, if a record is inserted or updated, the year of two date fields must be the same if active is 'Y'
create table MY_TABLE
(
id NUMBER not null,
active CHAR(1) ,
date_one DATE,
date_two DATE
)
/* Allowed : both dates are 2014 AND flag id 'Y'*/
insert into MY_TABLE(id, active, date_one, date_two)
VALUES (1, 'Y', to_date('20141201', 'yyyymmdd') , to_date('20140101', 'yyyymmdd');
/* DISAllowed : dates have different year AND flag id 'Y'*/
insert into MY_TABLE(id, active, date_one, date_two)
VALUES (2, 'Y', to_date('20151201', 'yyyymmdd') , to_date('20140101', 'yyyymmdd');
/* Allowed : dates have different year AND flag id is NOT 'Y'*/
insert into MY_TABLE(id, active, date_one, date_two)
VALUES (3, 'N', to_date('20151201', 'yyyymmdd') , to_date('20140101', 'yyyymmdd');
Many thanks
Upvotes: 0
Views: 749
Reputation: 52893
Adding a constraint is a matter of crafting some logic that accurately defines the business logic that you want to implement. In your case you want either ACTIVE
to be N
or the years in the date must be the same.
You can use the EXTRACT()
function in order to check the years; i.e.
SQL> select extract(year from sysdate) from dual;
EXTRACT(YEARFROMSYSDATE)
------------------------
2015
This makes your condition active = 'N' or extract(year from date_one) = extract(year from date_two)
, which you can then declare in your table DDL:
create table my_table (
id number not null
, active char(1)
, date_one date
, date_two date
, constraint chk_dates check (
active = 'N' or extract(year from date_one) = extract(year from date_two) )
);
which gives you the desired result:
SQL> insert into MY_TABLE(id, active, date_one, date_two)
2 VALUES (1, 'Y', to_date('20141201', 'yyyymmdd') , to_date('20140101', 'yyyymmdd'));
1 row created.
SQL> insert into MY_TABLE(id, active, date_one, date_two)
2 VALUES (2, 'Y', to_date('20151201', 'yyyymmdd') , to_date('20140101', 'yyyymmdd'));
insert into MY_TABLE(id, active, date_one, date_two)
*
ERROR at line 1:
ORA-02290: check constraint (REF.CHK_DATES) violated
SQL> insert into MY_TABLE(id, active, date_one, date_two)
2 VALUES (3, 'N', to_date('20151201', 'yyyymmdd') , to_date('20140101', 'yyyymmdd'));
1 row created.
I would also add separate constraints on the ACTIVE
column to ensure that it can only have the correct values and on your primary key
create table my_table (
id number not null
, active char(1)
, date_one date
, date_two date
, constraint pk_my_table primary key (id)
, constraint chk_my_table_active check ( active in ('Y', 'N') )
, constraint chk_dates check (
active = 'N' or extract(year from date_one) = extract(year from date_two) )
);
If you ACTIVE
column can have more values than Y or N then you need to change the constraint slightly to take this into account; for instance something like the following:
coalesce(active, 'X') <> 'Y' or extract(year from date_one) = extract(year from date_two)
Upvotes: 3