Bitemporal integrity checks

232 Views Asked by At

The need for this comes from the fact, that we now have numerous sources updating sensitive bi-temporal tables, we are a little bit alert and want to cover our backs.

I used "Developing Time-Oriented Database Applications in SQL" by Richard Snodgrass to aid me with this.

I've been trying to come up with a trigger that asserts bitemporal contracts are held after each update or insert. To be more specific the contracts ensure primary key is valid-time and transaction-time sequenced, and also non-sequenced valid time continuity assertion. After breaking this down assertions are as follows:

  1. Assert there are no overlaps in "active" VALID_TIME timeline.

  2. Assert there are no overlaps in TRANSACTION_TIME timeline.

  3. Assert there are no gaps in VALID_TIME timeline.

By "active" I mean the records with TRANSACTION_END value "forever" (9999-12-31).

Here's what I have so far:

CREATE OR REPLACE TRIGGER TRIGGER_NAME
    AFTER INSERT OR UPDATE
    ON SOME_TABLE
DECLARE
         ROWCOUNT INTEGER;
BEGIN
         SELECT COUNT(*) INTO ROWCOUNT
    FROM SOME_TABLE T1,SOME_TABLE T2
    WHERE T1.PK_COLUMN2 = T2.PK_COLUMN2
    AND T1.PK_COLUMN1 = T2.PK_COLUMN1
    AND T1.TRANSACTION_START < T2.TRANSACTION_END
    AND T2.TRANSACTION_START < T1.TRANSACTION_END
    AND T1.ROWID != T2.ROWID;

    IF (ROWCOUNT>0) THEN
      RAISE_APPLICATION_ERROR(-20001, 'BITEMPORAL INTEGRITY TRIGGER CHECK : AUDIT_TIME OVERLAP');
    END IF;

         SELECT COUNT(*) INTO ROWCOUNT
    FROM SOME_TABLE T1,SOME_TABLE T2
    WHERE T1.PK_COLUMN2 = T2.PK_COLUMN2
    AND T1.PK_COLUMN1 = T2.PK_COLUMN1
    AND T1.VALID_START < T2.VALID_END
    AND T2.VALID_START < T1.VALID_END
    AND T1.TRANSACTION_END = DATE '9999-12-31'
    AND T2.TRANSACTION_END = DATE '9999-12-31'
    AND T1.ROWID != T2.ROWID;

    IF (ROWCOUNT>0) THEN
      RAISE_APPLICATION_ERROR(-20001, 'BITEMPORAL INTEGRITY TRIGGER CHECK : ACTIVE VALID_TIME OVERLAP');
    END IF;

         SELECT COUNT(*) INTO ROWCOUNT
    FROM SOME_TABLE S, SOME_TABLE T2
    WHERE S.VALID_END < T2.VALID_START
    AND S.PK_COLUMN1 = T2.PK_COLUMN1
    AND S.PK_COLUMN2 = T2.PK_COLUMN2
    AND S.TRANSACTION_END = DATE '9999-12-31'
    AND T2.TRANSACTION_END = DATE '9999-12-31'
    AND NOT EXISTS (
    SELECT *
    FROM SOME_TABLE T3
    WHERE T3.PK_COLUMN1 = S.PK_COLUMN1
    AND T3.PK_COLUMN2 = S.PK_COLUMN2
    AND (((T3.VALID_START <= S.VALID_END)
    AND (S.VALID_END < T3.VALID_END))
    OR ((T3.VALID_START < T2.VALID_START)
    AND (T2.VALID_START <= T3.VALID_END)))
    AND T3.TRANSACTION_END = DATE '9999-12-31');

    IF (ROWCOUNT>0) THEN
      RAISE_APPLICATION_ERROR(-20001, 'BITEMPORAL TRIGGER CHECK : ACTIVE VALID_TIME CONTINUITY VIOLATED (GAPS)');
    END IF;
END;

PK_COLUMN(s) are the makings of natural keys, rest should be obvious.

The questions are as follows:

Did I include every possible scenario? Is there an additional contract, which I forgot to check against?

Bonus question, can you recommend any other solid book/resource on bi-temporal data architectures?

//Added some more tags, for greater reach...

Any comments, suggestions, constructive critique is welcome.

Thanks in advance,

Matt.

0

There are 0 best solutions below