0

I have created the following two tables for use in a history classroom setting. These tables will contain data about wars throughout history and the nations that were a part of them.

My problem is that the Wars table is not in 3NF because of the multiple values in the Combatants field, as there can be many combatants (i.e. nations) in a war.

How do I change this schema to 3NF without creating any artificial keys (i.e. only using the fields that I currently have)?

CREATE TABLE Wars (
  Name CHAR(50) PRIMARY KEY,
  StartingDate DATE NOT NULL,
  EndingDate DATE NOT NULL,
  Cause CHAR(50) NOT NULL,
  Combatants CHAR(50) NOT NULL,
  TodaysDate DATE DEFAULT SYSDATE,
  CONSTRAINT CHK_TD CHECK(EndingDate < TodaysDate),
  CONSTRAINT CHK_SD CHECK(StartingDate > 0);

CREATE TABLE Nations (
  Name CHAR(50) PRIMARY KEY,
  StartingDate DATE NOT NULL,
  EndingDate DATE,
  TodaysDate DATE DEFAULT SYSDATE,
  CONSTRAINT CHK_TD CHECK(EndingDate < TodaysDate);
ADyson
  • 57,178
  • 14
  • 51
  • 63
  • Does each combatant also have an association to a nation (or even nations)? – ADyson May 07 '19 at 21:04
  • Yes, each combatant would be a nation. – Todd Johnson May 07 '19 at 21:05
  • Oh I see you mean "combatants" are countries, not people or anything else. It helps to name the same entity the same way throughout your schema! So then I assume each nation can also appear in more than one war? If so then you need to implement a many-to-many relationship, with a 3rd table representing that relationship. – ADyson May 07 '19 at 21:06
  • Yes, you are correct. Combatants are countries, and each country can appear in multiple wars. – Todd Johnson May 07 '19 at 21:07
  • So remove the "combatants" field from your Wars table, and create a "NationsWars" table (or whatever you want to call it). It need only contain the Nation Name and War Name. These will each have a foreign key back to the primary key of their respective parent tables. The primary key of this new table will be a compound key consisting of both fields. This is the classic, standard way to represent a many-to-many relationship such as this – ADyson May 07 '19 at 21:09
  • 1
    BTW what's your objection to artificial keys here? I'd say numeric IDs would be ideal keys for the nations and wars tables...that way if a nation changes its name, or you realise you made a typo, or you want to re-label a war, then you can do so without violating any key constraints. It's generally considered bad practice to use name or description fields as keys, because they are almost always subject to change in the long term – ADyson May 07 '19 at 21:10
  • 1
    I wrote a formal answer for it below. If it helps you, please remember to mark it as accepted - thanks! P.S. on a purely academic note, how neat it would be if the causes of all wars could be summarised in a 50-character field, rather than the subject of endless books and papers! :-) – ADyson May 07 '19 at 21:19
  • "...without creating any artificial keys..." Artificial keys are not inherently bad. The efficiency gains are often worth their use, and they rarely have any particularly harmful effects on usage. If you really have a viable (small) true natural key for your data that you are 100% sure you will not have a changing value, go for it, but it's pretty rare to have them. – jpmc26 May 07 '19 at 22:15
  • Possible duplicate of [How to implement one-to-one, one-to-many and many-to-many relationships while designing tables?](https://stackoverflow.com/questions/7296846/how-to-implement-one-to-one-one-to-many-and-many-to-many-relationships-while-de) – jpmc26 May 07 '19 at 22:20
  • What is your question? PS One puts a schema into 3NF by following the algorithm for that in your textbook. Normalizaton to higher NFs uses FDs but you dont' mention them, so it seems you don't even understand basics. Right now you are just asking for us to rewrite your textbook/manual with a bespoke tutorial & do your (home)work & you have shown no research or other effort. Dumps of requirements are not on-topic questions. Please see [ask], hits googling 'stackexchange homework' & the voting arrow mouseover texts. Show what relevant parts you can do & explain re the first place you are stuck. – philipxy May 07 '19 at 22:41

1 Answers1

0

What you've got here is a many-to-many relationship where a war can feature multiple nations, and a nation can feature in multiple wars.

To represent this in your schema:

1) Remove the "combatants" field from your Wars table

2) Create a "NationsWars" table (or whatever you want to call it). It need only contain the Nation Name and War Name.

3) Each of these two fields will each have a foreign key back to the primary key of their respective parent tables.

4) The primary key of this new table will be a compound key consisting of both the fields mentioned above.

This is the classic, standard way to represent a many-to-many relationship such as this.


N.B. I'm unsure why you have an objection to artificial keys here. I'd say numeric auto-increment IDs would be ideal keys for the nations and wars tables...that way if a nation changes its name, or you realise you made a typo, or you want to re-label a war, then you can do so without violating any key constraints. It's generally considered bad practice to use name or description fields as keys, because they are almost always subject to change in the long term. The primary key should be something which uniquely and permanently identifies the specific record, and has no other contextual meaning.

ADyson
  • 57,178
  • 14
  • 51
  • 63
  • Thank you for your help! This should solve my problem. – Todd Johnson May 07 '19 at 21:22
  • 1
    It might be worth noting that the `NationsWars` table is what is sometimes referred to as a [bridge table](https://www.ibm.com/support/knowledgecenter/en/SSEP7J_11.1.0/com.ibm.swg.ba.cognos.ug_fm.doc/c_dyn_query_bridge_tables.html) or [associative entity](https://en.wikipedia.org/wiki/Associative_entity). Such tables are required to represent many-to-many relationships in SQL databases because they only natively support many-to-one relationships (via foreign keys). – jpmc26 May 07 '19 at 22:19
  • This has nothing to to do with normalization. – philipxy May 07 '19 at 22:45
  • @philipxy I'd be interested to know why you think that? The original data is in un-normalised form because of the repeating group in the "Combatants" field (it contained comma-separated values). So what we've done here is remove that problem. In order to create the correct link between the two tables we've also added a new table to represent the relationships. Since the Nations table already existed then we didn't need to add that as well. If that process isn't, for all practical purposes, normalisation, then maybe I don't know what is. Perhaps you could enlighten us? Cheers. – ADyson May 08 '19 at 07:58
  • Because it has nothing to do with normalization. The term is used to mean either or both of 2 different related things--normalization to "1NF" & normalization to higher NFs. The question mentions 3NF, so it is concerned at least with the latter. You don't need me to find out more. Read a textbook. It is not clear what the question means by "the multiple values in the Combatants field". By definition a relation can't contain multiple values for an attribute in a row. [There's no one meaning for "1NF" & tons of nonsense is passed on about it.](https://stackoverflow.com/a/40640962/3404097) – philipxy May 08 '19 at 08:25
  • @philipxy "By definition a relation can't contain multiple values for an attribute in a row" ...exactly, which means it's in un-normalised form. The field contains more than one value per row, which it should not. e.g. it perhaps contains "England, Germany, France, USA" when it should only contain one of those, to allow that field to be a foreign key to the Nations table...but of course that one-to-many structure doesn't satisfy the business requirement, so we create a separate table. That part I agree is not directly related to normalisation, but removing the multiple values per row is, IMO. – ADyson May 08 '19 at 08:45
  • @philipxy now, as you've noted, you can argue all day about the semantics of what counts as 0NF, 1NF etc...but clearly the data was definitely not in 3NF before. Would you say that it now is in 3NF, or not? If not, why not? Because if it is, then it answers the question...and clearly it satisfies the OP's requirement, since they accepted the answer. OTOH If you think the question should be worded differently, then go ahead and edit it. – ADyson May 08 '19 at 08:46
  • See my first comment. – philipxy May 08 '19 at 08:47
  • @philipxy repeating the same tautology over again is not useful to anyone. It's nothing to do with normalisation because it's nothing to do with normalisation...yeah, thanks for your "help", much appreciated. Like I said, if you don't like the question, go ahead and edit it, remove the normalisation tag, change the wording to whatever you think is more appropriate, and preserve the academic purity of your corner of SO... – ADyson May 08 '19 at 09:02