简体   繁体   中英

Oracle Constraint Date Check SQL

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

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; ie

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM