Oracle约束日期检查SQL

时间:2015-01-06 12:39:31

标签: sql oracle

我想在表上添加一个约束,以防止根据某些条件插入/更新记录。

更具体地说,如果插入或更新记录,如果活动为“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');

非常感谢

1 个答案:

答案 0 :(得分:3)

添加约束是制定一些准确定义您要实现的业务逻辑的逻辑的问题。在您的情况下,您希望ACTIVEN,或者日期中的年份必须相同。

您可以使用EXTRACT()功能查看年份;即

SQL> select extract(year from sysdate) from dual;

EXTRACT(YEARFROMSYSDATE)
------------------------
                    2015

这使您的条件active = 'N' or extract(year from date_one) = extract(year from date_two),然后您可以在表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) )
    );

为您提供所需的结果:

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.

我还会在ACTIVE列上添加单独的约束,以确保它只能包含正确的值和主键

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

如果ACTIVE列的值可能比Y或N多,那么您需要稍微更改约束以将其考虑在内;例如以下内容:

coalesce(active, 'X') <> 'Y' or extract(year from date_one) = extract(year from date_two)