Names are easy, right? Every single one of us has - at one time or another - built a table that looks like this, right?

CREATE TABLE dbo.Persons (
  PersonKey INT NOT NULL IDENTITY(1, 1),
  FirstName NVARCHAR(100) NOT NULL,
  MiddleName NVARCHAR(100) NOT NULL,
  LastName NVARCHAR(100) NOT NULL,
  CONSTRAINT [PK_dbo.Persons] PRIMARY KEY CLUSTERED (PersonKey)
);
PersonKey FirstName MiddleName LastName
123 Jonathan Q Public

We build our table like this because this is what we know. Sometimes old ways are old for a reason; sometimes old ways need to die.

Have you ever met someone who doesn’t have a middle name? I have. What do you put there? Do you save a null value? Do you make it an empty string? What about suffixes? What about titles? Do those become more columns? Again, you have to deal with null values and empty strings. Is there a business-relevant difference between a null and an empty string?

What about tracking maiden names? What about name changes? What about people who have more than three names? Names are way more complicated than initially expected.

You Don’t Need It

Most of the time, I am willing to make a bet that you do not need that information. What is the difference between three columns and one? For most line of business applications, there is no difference at all. I believe you would be much better off with the following design.

CREATE TABLE dbo.Persons (
  PersonKey INT NOT NULL IDENTITY(1, 1),
  FullLegalName NVARCHAR(200) NOT NULL,
  DisplayName NVARCHAR(200) NOT NULL,
  CONSTRAINT [PK_dbo.Persons] PRIMARY KEY CLUSTERED (PersonKey)
);

This results in a data structure that is probably much closer to what you want.

PersonKey FullLegalName DisplayName
123 Jonathan Q. Public Jonny Q.

You do not need last names in a separate column. If someone wants to be addressed as Dr. Smith, then store that as a column.

Names with Variable Parts

If you have names of differing lengths, I recommend storing names in a name table.

CREATE TABLE dbo.Names (
  NameKey INT NOT NULL IDENTITY(1, 1),
  PersonKey INT NOT NULL,
  Sequence INT NOT NULL,
  NamePart NVARCHAR(100) NOT NULL,
  CONSTRAINT [PK_dbo.Names] PRIMARY KEY CLUSTERED (NameKey),
  CONSTRAINT [FK_dbo.Names_PersonKey] FOREIGN KEY (PersonKey) REFERENCES dbo.Persons (PersonKey)
);
NameKey PersonKey Sequence NamePart
501 123 1 Jonathan
502 123 2 Q
503 123 3 Public

Naming the Variable Parts

We could also, just as easily, keep track of our different name parts. We have given names, middle names, family names, maiden names, religious names, nicknames,

CREATE TABLE dbo.NameTypes (
  NameTypeKey INT NOT NULL IDENTITY(1, 1),
  Description NVARCHAR(100) NOT NULL,
  CONSTRAINT [PK_dbo.NameTypes] PRIMARY KEY CLUSTERED (NameTypeKey)
);
NameTypeKey Description
1 First Name
2 Middle Name
3 Last Name
4 Nickname
5 Title
6 Suffix
7 Religious Name
8 Credentials

Our Names table now looks like the following.

CREATE TABLE dbo.Names (
  NameKey INT NOT NULL IDENTITY(1, 1),
  PersonKey INT NOT NULL,
  Sequence INT NOT NULL,
  NameTypeKey INT NOT NULL,
  NamePart NVARCHAR(100) NOT NULL,
  CONSTRAINT [PK_dbo.Names] PRIMARY KEY CLUSTERED (NameKey),
  CONSTRAINT [FK_dbo.Names_PersonKey] FOREIGN KEY (PersonKey) REFERENCES dbo.Persons (PersonKey),
  CONSTRAINT [FK_dbo.Names_NameTypeKey] FOREIGN KEY (NameTypeKey) REFERENCES dbo.NameTypes (NameTypeKey)
);
NameKey PersonKey Sequence NameTypeKey NamePart
501 123 2 1 Jonathan
502 123 3 2 Q
503 123 4 3 Public
504 123 1 5 Mr.
505 123 5 6 III
506 123 6 7 LMFT

I would also recommend that you add start and end dates to names, because names can change over time. Marriages happen and unhappen, and names can be legally changed.

NameKey PersonKey Sequence NameTypeKey NamePart StartDate EndDate
501 123 2 1 Jonathan 07-Mar-2018 31-Dec-9999
502 123 3 2 Q 07-Mar-2018 31-Dec-9999
503 123 4 3 Public 07-Mar-2018 31-Dec-9999
504 123 1 5 Mr. 07-Mar-2018 31-Dec-9999
505 123 5 6 III 07-Mar-2018 31-Dec-9999
506 123 6 7 LMFT 07-Mar-2018 31-Dec-9999

Now, we have a name structure that works across languages and cultures; it allows for growth without adding more columns to a names table; it easily allows for tracking changes; it keeps like types of data in the same column; and it is a simple matter to create a name view, joining rows by PersonKey.