Search code examples
foreign-keysrelational-databasedatabase-normalization3nf

Can you move compound keys and/or foreign keys to other tables when normalizing to 3NF (third normal form)


My database design is currently at 3NF. The issue is foreign keys and in some cases compound keys.

Can you move compound keys and/or foreign keys to create other tables provided the attributes associated with the compound/foreign keys do not rely on the primary key?

I suspect the answer is yes due to this link:

Are Foreign Keys included in Third Normal Form?
Best Answer: Just because it's a foreign key doesn't mean it also can't be considered an attribute of the primary key. The fact that it's a foreign key to begin with implies it's defining a relationship with another table, and thus would not violate [...] 3NF.
-- TheMadProfessor
https://answers.yahoo.com/question/index?qid=20081117095121AAXWBbX#

This leads me to wonder whether my current normalization stage is 3NF.


Solution

  • I'm not sure that I understand your question. If you are asking, "Can you have a foreign key in a table without violating 3NF?" the answer is absolutely, positively yes. Nothing about any stage of normalization says that you should eliminate foreign keys. Indeed, it's pretty much impossible to normalize all but the most trivial data without using foreign keys.

    ** Update **

    Okay, maybe now I understand your question, but then I think you've answered it for yourself. Yes, in a fully-normalized DB, you should not have non-key dependencies. If you have FKs that are not dependent on the PK, then they should be moved to another table.

    To make a simple example, suppose you want to keep track of people, the city they live in, and the country that that city is in. So for your first draft, you make this structure: (Asterisk marks the PK.)

    Person (person_id*, person_name, city_id, country_id)
    City (city_id*, city_name)
    Country (country_id*, country_name)
    

    This is not normalized. A city is in the same country regardless of what resident of that city we are talking about. Paris is not in France when we are talking about Pierre but in Germany when we are talking about Francois. (If there are two cities with the same name, of course those are different cities and should have different records. I suppose a city could cross national boundaries, but for our purposes here let's assume that if it does, we consider it two cities that happen to touch. They would surely have different city governments, different postal systems, etc.) So we have a non-key dependency. country_id depends on city_id, not on person_id.

    So to normalize this schema, we should move the country_id to a table where it is dependent solely on the PK. Presumably, the City table:

    Person (person_id*, person_name, city_id)
    City (city_id*, city_name, country_id)
    Country (country_id*, country_name)