Skip to Main Content
  • Questions
  • Database design to store multiple properties of an entity and to maintain its historical changes

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Vinod.

Asked: March 24, 2016 - 8:28 am UTC

Last updated: March 31, 2016 - 3:07 am UTC

Version: 11g

Viewed 1000+ times

You Asked

I need a database design to maintain the entity, its properties and also to store the historical changes of the property values
Entity: Any object. For example car
Properties: Color, Engine type, Height, Width
Example: I created a main table with obj_id and obj_name. Properties table with prop_id and prop_name

Create table object (obj_id number, obj_name varchar2, created_date, created_by,last_updated_by,start_date,end_date);
insert into object values(1,'Car');

create table obj_prop (prop_id number, prop_name varchar2, created_date, created_by,last_updated_by,start_date,end_date);
insert into obj_prop values (1,'Color');
insert into obj_prop values (2,'Engine_type');
insert into obj_prop values (3,'Height');
insert into obj_prop values (4,'width');

create table obj_prop_assoc (assoc_id number,obj_id number,prop_id number, prop_value varchar2, created_date, created_by,last_updated_by,start_date,end_date);
insert into obj_prop_assoc values (1,1,1,'White');
insert into obj_prop_assoc values (2,1,2,'Diesel');
insert into obj_prop_assoc values (3,1,3,'250cm');
insert into obj_prop_assoc values (4,1,4,'500cm');

So, If any new object/property has to be added I can add in above tables.

Question

1.Is this is the best design to follow?

2. How can I apply constraints on property values?

If I have another table to store different colors
Create table colors(color_id,color_name)
insert into colors(1,'Violet');
insert into colors(2,'Indigo');
insert into colors(3,'Blue');
insert into colors(4,'Green');
insert into colors(5,'Yellow');
insert into colors(6,'Orange');
insert into colors(7,'Red');

Now I want to apply constraint on obj_prop_assoc table prop_name column to have one of the values from the colors table for Color property (Foreign Key Constraint) . How can I do this?

Thanks.

and Chris said...

1. No! This is a form of entity-attribute-value (EAV) model.

There are many problems with this. See this thread:

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2314483800346542969

2. You can create the foreign key just like normal. But what if you want do the same for engine types? (petrol, diesel, etc.)

You can create another foreign key on the same column to the engine types table. But now you have a problem. You can't insert any data! (unless you happen to have engine types and colors which are the same).

"Optional" foreign keys, which only applies based on values from other columns are impossible. They apply to all rows in the table.

This is one of the big problems with EAV. It's almost impossible to enforce constraints such as "rows of type color must use values from the color table".

Just create a simple table:

create table cars (
  color       varcahr2(30),
  engine_type varchar2(30),
  height      number,
  width       number,
  ...
);


If you need to track changes to the data you could create some history tables. e.g.:

create table cars_hist (
  color       varcahr2(30),
  engine_type varchar2(30),
  height      number,
  width       number,
  ...
  changed_date date,
  change_type  varchar2(1),
  changed_by   varchar2(30),
  ...
);


Then write code/triggers to maintain this.

Or check out flashback data archive. It does this all for you! If you're on 11.2.0.4 it's included in EE (it used to require a separate license).

https://oracle-base.com/articles/12c/flashback-data-archive-fda-enhancements-12cr1

Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thanks for reply...

Vinod, March 27, 2016 - 10:21 am UTC

Chris,

If I create a object and give sysdate as start_time and sysdate+2 as end_time. I want to give some default color/ no color if this object is used in the time period of sysdate and sysdate+1 and color 'Red' form sysdate+1 to sysdate+2.

One thing I can do is first insert a object record with null value for color.
On the next day i.e., sysdate+1 I have to update the color of this object to 'Red' and insert a record in history table.

Can I give this color property time period at the time of object insertion? How can I give different time periods for different attributes of single entity?
Connor McDonald
March 29, 2016 - 1:37 pm UTC

What do the colours mean? What's the whole algorithm? Why are you doing this?

From the sounds of things you're going to need to build your own functions. These will accept the start/end times and return the correct colour.

"How can I give different time periods for different attributes of single entity?"

What do you mean by "different time period"? What shows they're different?

The easiest way will be to create a table for each group of attributes that belong in a distinct period.

I'm not sure what your end goal is here though. What business problem are you solving?

Oracle Workspace Functionality as an alternative?

Johan Snyman, March 30, 2016 - 3:34 pm UTC

You could also achieve versioning of the data in your table(s) by using Oracle workspace functionality - see http://www.oracle.com/technetwork/documentation/index-087067.html
Depending on what you want to achieve, this may be overkill though.
Chris Saxon
March 31, 2016 - 3:07 am UTC

True, and also temporal validity would be worth exploration when you get to 12c.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library