Declarative approach to constrain data ranges in table

前端 未结 2 763
终归单人心
终归单人心 2021-01-14 07:23

I would like to learn a declarative approach for a data constraint issue I have had from time to time related to exclusive date ranges.

Below is a simplified example

2条回答
  •  暗喜
    暗喜 (楼主)
    2021-01-14 08:21

    While waiting for next Oracle 12c version, which supports Temporal Validity, I still use next approach:

    create table item ( title varchar2(32) primary key );
    create table price ( 
       price_id          number primary key,
       item              varchar2(32) not null references item (title), 
       price             number(9,2), 
       effective_from    date not null, 
       effective_to      date not null, 
       effective_prev_to date,
       constraint price_from_to_ck check ( effective_to > effective_from ),
       constraint price_to_prev_ck check ( effective_from = effective_prev_to + 1 ),
       constraint price_from_uq unique ( item, effective_to ),
       constraint price_dates_chain_fk foreign key ( item, effective_prev_to ) references price ( item, effective_to ) );
    
    insert into item values ('LETTUCE');
    insert into item values ('WHISKY');
    
    insert into price values ( 1, 'LETTUCE', 1.05, date '2013-01-01', date '2013-03-31', null );
    insert into price values ( 2, 'LETTUCE', 1.08, date '2013-04-01', date '2013-06-30', date '2013-03-31' ); 
    insert into price values ( 3, 'WHISKY', 33.99, date '2013-01-01', date '2013-05-31', null );
    insert into price values ( 4, 'WHISKY', 31.15, date '2013-06-01', date '2013-07-31', date '2013-05-31' ); 
    

    Let's try:

    insert into price values ( 5, 'WHISKY', 30.55, date '2013-05-15', date '2013-06-05', date '2013-05-14' ); 
    
    ORA-02291: integrity constraint (USER_4_E7DF1.PRICE_DATES_CHAIN_FK) violated - parent key not found : insert into price values ( 'WHISKY', 30.55, date '2013-05-15', date '2013-06-05', date '2013-05-14' )
    

    But now updating and deleting dates in the middle of the chain is pain in the ass. It needs to change preceding and following rows in one statement with MERGE. That's why I've added price_id column, because you can't update a key in MERGE -- so, you need another key instead of (item, effective_%).

提交回复
热议问题