如果我按照您的要求进行操作,您可以使用基于函数的唯一索引来执行此操作:
create table card_service (
id_number number, begin_date date, service_type number, end_date date,
is_active varchar2(5),
constraint ck_is_active check (is_active in ('TRUE', 'FALSE'))
);
Table created.
create unique index ui_card_service on card_service (
case when is_active = 'TRUE' then id_number else null end,
case when is_active = 'TRUE' then service_type else null end
);
Index created.
空值不包含在索引中,因此您将只有TRUE
记录的索引“条目”,并且将case
语句应用于两个字段意味着结果在这两列中仍然是唯一的。
尝试为相同的id_number
and插入两条记录service_type
,都is_active
设置为TRUE
,失败:
insert into card_service values (1, date '2013-01-01', 1, null, 'TRUE');
1 row created.
insert into card_service values (1, date '2013-01-02', 1, null, 'TRUE');
insert into card_service values (1, date '2013-01-02', 1, null, 'TRUE')
*
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.UI_CARD_SERVICE) violated
将现有记录更新为FALSE
first 允许TRUE
添加新记录;
update card_service set is_active = 'FALSE'
where id_number = 1 and service_type = 1 and is_active = 'TRUE';
1 row updated.
insert into card_service values (1, date '2013-01-02', 1, null, 'TRUE');
1 row created.
你可以继续这样做:
update card_service set is_active = 'FALSE'
where id_number = 1 and service_type = 1 and is_active = 'TRUE';
1 row updated.
insert into card_service values (1, date '2013-01-03', 1, null, 'TRUE');
1 row created.
您可以为其他组合添加TRUE
记录:
insert into card_service values (1, date '2013-01-04', 2, null, 'TRUE');
insert into card_service values (2, date '2013-01-05', 1, null, 'TRUE');
insert into card_service values (2, date '2013-01-06', 2, null, 'TRUE');
所以你最终得到:
select * from card_service;
ID_NUMBER BEGIN_DAT SERVICE_TYPE END_DATE IS_AC
---------- --------- ------------ --------- -----
1 01-JAN-13 1 FALSE
1 02-JAN-13 1 FALSE
1 03-JAN-13 1 TRUE
1 04-JAN-13 2 TRUE
2 05-JAN-13 1 TRUE
2 06-JAN-13 2 TRUE
但是,将(可能是旧的)记录保留在单独的历史表中会更正常,因此您的主表只有当前记录(无论是TRUE
还是FALSE
)。