189

I'm just getting started working with foreign keys for the first time and I'm wondering if there's a standard naming scheme to use for them?

Given these tables:

task (id, userid, title)
note (id, taskid, userid, note);
user (id, name)

Where Tasks have Notes, Tasks are owned by Users, and Users author Notes.

How would the three foreign keys be named in this situation? Or alternatively, does it even matter at all?

Update: This question is about foreign key names, not field names!

chills42
  • 14,201
  • 3
  • 42
  • 77
nickf
  • 537,072
  • 198
  • 649
  • 721
  • 10
    Note for readers: Many of the best practices listed below do not work in Oracle because of its 30 character name limit. A table name or column name may already be close to 30 characters, so a convention combining the two into a single name requires a truncation standard or other tricks. – Charles Burns Nov 29 '14 at 18:34
  • Possible duplicate of [Naming of ID columns in database tables](https://stackoverflow.com/questions/208580/naming-of-id-columns-in-database-tables) – philipxy Jul 07 '19 at 22:01

10 Answers10

216

The standard convention in SQL Server is:

FK_ForeignKeyTable_PrimaryKeyTable

So, for example, the key between notes and tasks would be:

FK_note_task

And the key between tasks and users would be:

FK_task_user

This gives you an 'at a glance' view of which tables are involved in the key, so it makes it easy to see which tables a particular one (the first one named) depends on (the second one named). In this scenario the complete set of keys would be:

FK_task_user
FK_note_task
FK_note_user

So you can see that tasks depend on users, and notes depend on both tasks and users.

Greg Beech
  • 133,383
  • 43
  • 204
  • 250
  • 1
    If the foreign key points to a candidate key on the second table rather than a primary key, then you'd probably use a third segment to the name to qualify this. It's an unusual situation to be in, and not one you'd typically design in from scratch, so I didn't include this in the response. – Greg Beech Oct 14 '08 at 00:41
  • 5
    You include the current table name in the key to keep it distinct. FK names are in the global namespace in SQL Server so you can't have two FKs named FK_PrimaryKeyTable attached to two different foreign key tables. The rules may be different for other database servers. – Greg Beech Oct 14 '08 at 00:43
  • Okay ... I have different namespaces for each table in Oracle, so I don't need the self reference. – Steve Moyer Oct 14 '08 at 00:47
  • 39
    This seems to be the common use but what to people do when there are two foreign keys pointing to the same table. i.e. `message` table has a `from_user_id` and `to_user_id` both of those would become `fk_message_user`. It seem to me better to use `fk_tablename_columnname` (fk_message_from_user_id in my example) for this reason and then try to keep your column names clear about the target table (i.e. to_user_id is clearly referring to the user table) – Code Commander Jan 11 '13 at 20:50
  • 1
    what if both the table itself have underscores for ex. user_role and user_addresses? fk_user_addresses_user_role isn't it confusing? – Govinda Sakhare Jun 18 '15 at 11:25
  • @govi Yes it does get confusing (i've had to do it for Oracle). But for SQL Server [pascal case is preferred to underscores](http://stackoverflow.com/a/3593804/345659). I've usually just suffixed the column name to the end - ie `FK_UserAddresses_UserRole_ToUserID` and `FK_UserAddresses_UserRole_FromUserID` – JumpingJezza Jun 25 '15 at 01:14
  • @GregBeech Also, you might want to add a number suffix to these names, if there's a possibility of multiple relations between two tables. For example, a user might be "supervising" multiple tasks. In such situations, you might name the two foreign keys as `FK_task_user_1`, `FK_task_user_2`. Also you can use two underscore characters as delimiter (in case of tables having underscore in their names) to improve readability as suggested by [onedaywhen](http://stackoverflow.com/questions/199498/foreign-key-naming-scheme#answer-200253). – Nikunj Madhogaria Aug 16 '15 at 13:42
54

I use two underscore characters as delimiter i.e.

fk__ForeignKeyTable__PrimaryKeyTable 

This is because table names will occasionally contain underscore characters themselves. This follows the naming convention for constraints generally because data elements' names will frequently contain underscore characters e.g.

CREATE TABLE NaturalPersons (
   ...
   person_death_date DATETIME, 
   person_death_reason VARCHAR(30) 
      CONSTRAINT person_death_reason__not_zero_length
         CHECK (DATALENGTH(person_death_reason) > 0), 
   CONSTRAINT person_death_date__person_death_reason__interaction
      CHECK ((person_death_date IS NULL AND person_death_reason IS NULL)
              OR (person_death_date IS NOT NULL AND person_death_reason IS NOT NULL))
        ...
onedaywhen
  • 55,269
  • 12
  • 100
  • 138
  • 4
    This is absolutely the best answer. – Frederik Krautwald Apr 30 '15 at 09:30
  • 1
    I just created Derby DB with very specific naming convention and this one here is the most readable and traceable. Thank you – Anddo Oct 12 '19 at 13:08
  • 1
    I guess the thing about using table names only is ... two foreign keys pointing to the same target table ... this is why I might be inclined to include field names... complicated subject no doubt. – spencer741 Feb 06 '21 at 01:22
21

How about FK_TABLENAME_COLUMNNAME?

Keep It Simple Stupid whenever possible.

Appulus
  • 18,630
  • 11
  • 38
  • 46
EvilTeach
  • 28,120
  • 21
  • 85
  • 141
  • 28
    Because when you have a huge db with a lot of keys and tables and you get an error during a schema update in your software it's pretty hard to find where the foreign key is even defined without doing a search of a database create script. – JohnC Apr 11 '12 at 00:05
  • 3
    @JohnC if the FK column names have the other table name in the column name then shouldn't it be very easy to tell? It tells you the two tables and the column name it's defined on. Ex: `FK_Animals_OwnerID`—Animals and Owners table, defined on OwnerID column – David Sherret Jun 06 '16 at 18:22
  • I would generally expect the error message to include the FK name. From there it is a simple query lookup to find the details. – EvilTeach Jul 05 '22 at 15:56
16

A note from Microsoft concerning SQL Server:

A FOREIGN KEY constraint does not have to be linked only to a PRIMARY KEY constraint in another table; it can also be defined to reference the columns of a UNIQUE constraint in another table.

so, I'll use terms describing dependency instead of the conventional primary/foreign relationship terms.

When referencing the PRIMARY KEY of the independent (parent) table by the similarly named column(s) in the dependent (child) table, I omit the column name(s):

FK_ChildTable_ParentTable

When referencing other columns, or the column names vary between the two tables, or just to be explicit:

FK_ChildTable_childColumn_ParentTable_parentColumn
bvj
  • 3,294
  • 31
  • 30
  • 2
    +1 I found that, although verbose, the last example you provide is the least confusing and most straight forward. I would even use the double underscoring like @onedaywhen suggests in his answer for tables that have an underscore in the name. I personally only use the underscore in cross-reference tables. – spencer741 Feb 06 '21 at 01:26
10

I usually just leave my PK named id, and then concatenate my table name and key column name when naming FKs in other tables. I never bother with camel-casing, because some databases discard case-sensitivity and simply return all upper or lower case names anyway. In any case, here's what my version of your tables would look like:

task (id, userid, title);
note (id, taskid, userid, note);
user (id, name);

Note that I also name my tables in the singular, because a row represents one of the objects I'm persisting. Many of these conventions are personal preference. I'd suggest that it's more important to choose a convention and always use it, than it is to adopt someone else's convention.

Steve Moyer
  • 5,663
  • 1
  • 24
  • 34
  • heh - this is the exact style I'm actually using (but with camelCase)- I thought I'd add a bit of extra description into the names for the purposes of illustrating their linkages. – nickf Oct 14 '08 at 00:11
  • So at least we can read each other's schemas;) ... what's embarassing is not being able to read your own after a couple years of absence. We use ERWin to diagram our schemas, but it's often convenient to have a text version and having a convention let's you find tables and fields easily. – Steve Moyer Oct 14 '08 at 00:15
6

This is probably over-kill, but it works for me. It helps me a great deal when I am dealing with VLDBs especially. I use the following:

CONSTRAINT [FK_ChildTableName_ChildColName_ParentTableName_PrimaryKeyColName]

Of course if for some reason you are not referencing a primary key you must be referencing a column contained in a unique constraint, in this case:

CONSTRAINT [FK_ChildTableName_ChildColumnName_ParentTableName_ColumnInUniqueConstaintName]

Can it be long, yes. Has it helped keep info clear for reports, or gotten me a quick jump on that the potential issue is during a prod-alert 100% would love to know peoples thoughts on this naming convention.

SSISPissesMeOff
  • 412
  • 1
  • 5
  • 15
  • 1
    In mysql, the limit is 64 chars. So, your example it is the most apropiate solution, but not resolves all situations. Some times, the FK is bigger than 64 chars. Just imagine the tables and columns name given in your example are correct. Your FK name `FK_ChildTableName_ChildColumnName_ParentTableName_ColumnInUniqueConstaintName` is too long... – Andrei Jul 27 '21 at 14:52
3

My usual approach is

FK_ColumnNameOfForeignKey_TableNameOfReference_ColumnNameOfReference

Or in other terms

FK_ChildColumnName_ParentTableName_ParentColumnName

This way I can name two foreign keys that reference the same table like a history_info table with column actionBy and actionTo from users_info table

It will be like

FK_actionBy_usersInfo_name - For actionBy
FK_actionTo_usersInfo_name - For actionTo

Note that:

I didn't include the child table name because it seems common sense to me, I am in the table of the child so I can easily assume the child's table name. The total character of it is 26 and fits well to the 30 character limit of oracle which was stated by Charles Burns on a comment here

Note for readers: Many of the best practices listed below do not work in Oracle because of its 30 character name limit. A table name or column name may already be close to 30 characters, so a convention combining the two into a single name requires a truncation standard or other tricks. – Charles Burns

Community
  • 1
  • 1
Cary Bondoc
  • 2,923
  • 4
  • 37
  • 60
  • 1
    Your one will failed if you have 3rd table have the FK point to ParentTableName_ParentColumnName same table by duplicate FK_Name – Tony Dong Jun 12 '17 at 17:31
0

Based on the answers and comments here, a naming convention which includes the FK table, FK field, and PK table (FK_FKTbl_FKCol_PKTbl) should avoid FK constraint name collisions.

So, for the given tables here:

fk_task_userid_user
fk_note_userid_user

So, if you add a column to track who last modified a task or a note...

fk_task_modifiedby_user
fk_note_modifiedby_user
Chad Kieffer
  • 491
  • 4
  • 8
-2

If you aren't referencing your FK's that often and using MySQL (and InnoDB) then you can just let MySQL name the FK for you.

At a later time you can find the FK name you need by running a query.

user12345
  • 2,876
  • 2
  • 24
  • 25
  • 4
    I can only explain my down-vote. Just about every database system allows for the system to name constraints, Can you imagine going back and trying to quickly figure out during a production issue w/ a 100 table database even, trying to decipher what relationship FK__123ee456ff relates to? It is plain and simply put a HORRIBLE practice. When you build an index on this FK then what? system names that too? so when index IX_007e373f5963 is 98% fragmented how will you know where to look to figure out why? It just shouldn't be done. – SSISPissesMeOff Feb 17 '16 at 23:33
-4

Try using upper-cased Version 4 UUID with first octet replaced by FK and '_' (underscore) instead of '-' (dash).

E.g.

  • FK_4VPO_K4S2_A6M1_RQLEYLT1VQYV
  • FK_1786_45A6_A17C_F158C0FB343E
  • FK_45A5_4CFA_84B0_E18906927B53

Rationale is the following

  • Strict generation algorithm => uniform names;
  • Key length is less than 30 characters, which is naming length limitation in Oracle (before 12c);
  • If your entity name changes you don't need to rename your FK like in entity-name based approach (if DB supports table rename operator);
  • One would seldom use foreign key constraint's name. E.g. DB tool usually shows what the constraint applies to. No need to be afraid of cryptic look, because you can avoid using it for "decryption".
coldserenity
  • 21
  • 1
  • 2
  • 1
    These cryptic identifiers are what I was originally trying to get away from... I know MSSQL defaults to `sourcetable_targettable_uid` or something of that nature... even though the constraint names aren't used often, I think the idea is to have a human-readable naming scheme for version compliance, but also to not have to perform an extra step to get at the constraint name. At least this is the way I see it. – spencer741 Feb 06 '21 at 05:22