patternMinor
Enforce data integrity with a recursive table
Viewed 0 times
enforceintegritywithrecursivedatatable
Problem
I have an existing oracle 11g database schema that works with a web application. I am planning an expansion to the application so a web service can do data operations on the database. As part of the planning I have realized that there are no data integrity checks on parent/child relationships which would make it problematic to let other applications work with the table. I am planning to do validation in the web service but the best practice is to have validation in the database and the web service.
These are the problems I have identified:
--the base lookup table has a table with text values that is not shown.
--Example Red, Green,
CREATE TABLE PROPERTY
(
ID NUMBER(9) NOT NULL, --PRIMARY KEY
TENANT_ID NUMBER(9) NOT NULL
)
-- a property may or may not have a parent property.
--Example "Weight" of an item is a child of the "Shipping Weight"
CREATE TABLE PROPERTY_DEPENDENCY --PRIMARY KEY PROPERTY_ID,PROPERTY_TYPE_ID
(
PROPERTY_ID NUMBER(9) NOT NULL,
PARENT_PROPERTY_ID NUMBER(9),
PROPERTY_TYPE_ID NUMBER(9) NOT NULL,
ACTIVE NUMBER(1) NOT NULL
)
--examples "Item Colour", "Item Trim Colour","Shipping Weight", "Weight"
CREATE TABLE PROPERTY_TYPE
(
ID NUMBER(9) NOT NULL, --PRIMARY KEY
VALUE VARCHAR2(200 BYTE) NOT NULL,
PROPERTY_TYPE NUMBER(10) DEFAULT 1 NOT NULL
)
--and the table that you insert and update into
CREATE TABLE CASE_PROPERTY
(
ID NUMBER(9) NOT NULL, --PRIMARY KEY
PARENT_ID NUMBER(9), --constraint on PROPERTY
CASE_ID NUMBER(9) NOT NULL,--foreign key
PROPERTY_ID NUMBER(9), --constraint on PROPERTY
PROPERTY_TYPE_ID NUMBER(9) NOT NULL --constraint on PROPERTY_TYPE
)These are the problems I have identified:
- you can insert in
Solution
Do not know if this will be useful to you because it requires quite a few changes, but the problem is interesting, so I'll try.
These would be the major changes
Note that with the tree closure, each ancestor node points to itself as a descendant, meaning that in
It is not clear to me is a parent allowed to be any ancestor or just the one first step up. The closure table exposes ancestor and all descendants, so
-
Propagating AK
-
Using composite key in
Here are main constraints from the model to clarify relationships (you may need to modify syntax)
These would be the major changes
- Using the tree closure instead of the adjacency list for the reference hierarchy. The closure table contains paths form each parent to all of it descendants, so all possible parent-child combinations are exposed.
Note that with the tree closure, each ancestor node points to itself as a descendant, meaning that in
CaseProperty recursion stops on ID = ParentID instead on ParentID is NULL It is not clear to me is a parent allowed to be any ancestor or just the one first step up. The closure table exposes ancestor and all descendants, so
Level Difference is added to the TreeClosure, which is sub-typed as AllowedCombos for LevelDifference in (0,1).-
Propagating AK
{PropertyID, PropertyTypeID} instead of just PropertyID-
Using composite key in
CasePropertyHere are main constraints from the model to clarify relationships (you may need to modify syntax)
ALTER TABLE Property ADD
CONSTRAINT PK_PR PRIMARY KEY (PropertyID)
, CONSTRAINT AK1_PR UNIQUE (PropertyID ,PropertyTypeID)
, CONSTRAINT FK1_PR FOREIGN KEY (PropertyTypeID)
REFERENCES PropertyType(PropertyTypeID)
;
ALTER TABLE TreeClosure ADD
CONSTRAINT PK_TC PRIMARY KEY (AncestorID ,DescendantID ,AncestorTypeID ,DescendantTypeID)
, CONSTRAINT FK1_TC FOREIGN KEY (AncestorID ,AncestorTypeID)
REFERENCES Property(PropertyID ,PropertyTypeID)
, CONSTRAINT FK2_TC FOREIGN KEY (DescendantID ,DescendantTypeID)
REFERENCES Property(PropertyID ,PropertyTypeID)
;
ALTER TABLE CaseProperty ADD
CONSTRAINT PK_CP PRIMARY KEY (CaseID, PropertyID, PropertyTypeID)
, CONSTRAINT FK1_CP FOREIGN KEY (CaseID)
REFERENCES Case(CaseID)
, CONSTRAINT FK2_CP FOREIGN KEY (PropertyID ,PropertyTypeID)
REFERENCES Property(PropertyID ,PropertyTypeID)
, CONSTRAINT FK4_CP FOREIGN KEY (ParentCaseID ,ParentPropertyID ,ParentPropertyTypeID)
REFERENCES CaseProperty(CaseID ,PropertyID ,PropertyTypeID)
, CONSTRAINT FK5_CP FOREIGN KEY (ParentPropertyID ,PropertyID , ParentPropertyTypeID ,PropertyTypeID)
REFERENCES AllowedCombos(AncestorID ,DescendantID , AncestorTypeID ,DescendantTypeID)
;Code Snippets
ALTER TABLE Property ADD
CONSTRAINT PK_PR PRIMARY KEY (PropertyID)
, CONSTRAINT AK1_PR UNIQUE (PropertyID ,PropertyTypeID)
, CONSTRAINT FK1_PR FOREIGN KEY (PropertyTypeID)
REFERENCES PropertyType(PropertyTypeID)
;
ALTER TABLE TreeClosure ADD
CONSTRAINT PK_TC PRIMARY KEY (AncestorID ,DescendantID ,AncestorTypeID ,DescendantTypeID)
, CONSTRAINT FK1_TC FOREIGN KEY (AncestorID ,AncestorTypeID)
REFERENCES Property(PropertyID ,PropertyTypeID)
, CONSTRAINT FK2_TC FOREIGN KEY (DescendantID ,DescendantTypeID)
REFERENCES Property(PropertyID ,PropertyTypeID)
;
ALTER TABLE CaseProperty ADD
CONSTRAINT PK_CP PRIMARY KEY (CaseID, PropertyID, PropertyTypeID)
, CONSTRAINT FK1_CP FOREIGN KEY (CaseID)
REFERENCES Case(CaseID)
, CONSTRAINT FK2_CP FOREIGN KEY (PropertyID ,PropertyTypeID)
REFERENCES Property(PropertyID ,PropertyTypeID)
, CONSTRAINT FK4_CP FOREIGN KEY (ParentCaseID ,ParentPropertyID ,ParentPropertyTypeID)
REFERENCES CaseProperty(CaseID ,PropertyID ,PropertyTypeID)
, CONSTRAINT FK5_CP FOREIGN KEY (ParentPropertyID ,PropertyID , ParentPropertyTypeID ,PropertyTypeID)
REFERENCES AllowedCombos(AncestorID ,DescendantID , AncestorTypeID ,DescendantTypeID)
;Context
StackExchange Database Administrators Q#36698, answer score: 3
Revisions (0)
No revisions yet.