Search code examples
sqlsql-serverentity-frameworkentity-framework-6

Why is it a bad idea to have a table without a primary key?


I am very new to data modeling, and according to Microsoft's Entity Framework, tables without primary keys are not allowed and apparently a bad idea. I am trying to figure out why this is a bad idea, and how to fix my model so that I do not have this hole.

I have 4 tables in my current model: User, City, HelloCity, and RateCity. It is modeled as shown in the picture. The idea is that many users can visit many cities, and a user can only rate a city once, but they can greet a city many times. For this reason, I did not have a PK in HelloCity table.

Any insight as to how I can change this to comply with best practices, and why this is against best practices to begin with?

enter image description here


Solution

  • This response is mainly opinion/experience-based, so I'll list a few reasons that come to mind. Note that this is not exhaustive.

    Here're some reasons why you should use primary keys (PKs):

    1. They allow you to have a way to uniquely identify a given row in a table to ensure that there're no duplicates.
    2. The RDBMS enforces this constraint for you, so you don't have to write additional code to check for duplicates before inserting, avoiding a full table scan, which implies better performance here.
    3. PKs allow you to create foreign keys (FKs) to create relations between tables in a way that the RDBMS is "aware" of them. Without PKs/FKs, the relationship only exists inside the programmer's mind, and the referenced table might have a row with its "PK" deleted, and the other table with the "FK" still thinks the "PK" exists. This is bad, which leads to the next point.
    4. It allows the RDBMS to enforce integrity constraints. Is TableA.id referenced by TableB.table_a_id? If TableB.table_a_id = 5 then, you're guaranteed to have a row with id = 5 in TableA. Data integrity and consistency is maintained, and that is good.
    5. It allows the RDBMS to perform faster searches b/c PK fields are indexed, which means that a table doesn't need to have all of its rows checked when searching for something (e.g. a binary search on a tree structure).

    In my opinion, not having a PK might be legal (i.e. the RDBMS will let you), but it's not moral (i.e. you shouldn't do it). I think you'd need to have extraordinarily good/powerful reasons to argue for not using a PK in your DB tables (and I'd still find them debatable), but based on your current level of experience (i.e. you say you're "new to data modeling"), I'd say it's not yet enough to attempt justifying a lack of PKs.

    There're more reasons, but I hope this gives you enough to work through it.

    As far as your M:M relations go, you need to create a new table, called an associative table, and a composite PK in it, that PK being a combination of the 2 PKs of the other 2 tables.

    In other words, if there's a M:M relation between tables A and B, then we create a table C that has a 1:M relation to with both tables A and B. "Graphically", it'd look similar to:

    +---+ 1  M +---+ M  1 +---+
    | A |------| C |------| B |
    +---+      +---+      +---+
    

    With the C table PK somewhat like this:

    +-----+
    |  C  |
    +-----+
    | id  |  <-- C.id = A.id + B.id (i.e. combined/concatenated, not addition!)
    +-----+
    

    or like this:

    +-------+
    |   C   |
    +-------+
    | a_id  |  <--|
    +-------+     +-- composite PK columns instead
    | b_id  |  <--|   of concatenation (recommended)
    +-------+