0

Let's assume we have following database:

enter image description here

Or in pseudo sql format (all columns are not null):

create table road (
  id int PK
) 
create table item_on_road (
  id int PK
  road_id int FK road.id
  position_order int
  UNIQUE (road_id, position_order)
)
create table rock (
  id int PK FK item_on_road.id
  size float
)
// and so on

We have a road on which we can travel in one direction.

Along the road we can find different things item_on_road in order we encounter them position_order like 1,2,3

Things that we find on the road can be different, from sign to gas_station.

Now I would like to ask a questions:

  1. Does this database design corresponds to db 1-5th normal forms? I would assume not, because we can create item_on_road entry without corresponding rock

  2. If it doesn't corresponds 5th normal form, how to do so?

Optional questions:

  1. If answer to 1 question is yes, how to ensure existence of rock if item_on_road created?

  2. If answer to 1 question is yes, how to ensure we can't create rock and sign pointing to the same id?

1
  • Please ask 1 specific researched non-duplicate question. PS NF definitions & algorithms are faqs. How are you 1st stuck? How to Ask Help center
    – philipxy
    Nov 22, 2023 at 5:35

1 Answer 1

1

Fifth Normal Form is about defining the set of valid combinations, if you have a need to enforce that in the database design.

It's not about requiring that a row exist in a referencing table. I don't know of any Normal Form that does that.

For example, if you needed to make the database design enforce that rocks can only occur on roads 12 and 34, you would decompose into another table to represent valid combinations.

Your current design allows rocks to appear on any road. If that's your intention, then it complies with Fifth Normal Form.

Question 3 & 4: how to ensure that there exists a child row, and that an item can only be one type of item?

You would need to reverse the reference:

Add a foreign key column for rock in item_on_road, which references the rock table:

alter table item_on_road
  add column rock_id int,
  add foreign key (rock_id) references rock(id);

This foreign key column is nullable. If the item is a rock, then fill in the value. If the item is not a rock, then leave it null.

Add more columns for the other types of items.

Then add a CHECK constraint to make sure that exactly one of these foreign key columns is non-null.

alter table item_on_road
  add check (
    case when rock_id is null then 1 else 0 end
    + case when sign_id is null then 1 else 0 end
    ...
  ) = 1;
2
  • It looks doesn't right to me to have multiple nullable ref columns in item_on_road table from database design perspective, seems like redundant data, but it solves my questions and simplifies a fetch as I can just join tables, thanks. I will accept your answer if there will be no better options.
    – ZiiMakc
    Nov 16, 2023 at 21:05
  • 1
    Understandable. Frankly, most software developers just enforce this type of rule in application code. It might be handy to have the database enforce it so you are sure bugs in your code can never create anomalies in the data, but doing so comes with some inconvenience. Nov 16, 2023 at 21:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.