3

I have get an intermediate table ArticleLanguage

idArticleLanguage
ArticleId
LanguageId
Name

Foreign keys are:

ArticleId
LanguageId

Should I use primary keys for:

ArticleId
LanguageId

Because these fields are primary keys in related tables?

StuartLC
  • 104,537
  • 17
  • 209
  • 285
Jessie
  • 373
  • 2
  • 6
  • 17
  • 1
    You'd have a composite primary key on both those columns. – Martin Smith Jan 01 '18 at 17:02
  • It seems you have already added a surrogate key idArticleLanguage. Assuming the link can be established just the once, as per Martin, suggest drop the surrogate and use ArticleId, LanguageId as a composite PK. – StuartLC Jan 01 '18 at 17:09
  • Only 1 primary key allowed per table. – P.Salmon Jan 01 '18 at 17:13
  • 1
    Not related to your question, but what is the purpose of the `name` field? – Dan Bracuk Jan 01 '18 at 17:43
  • Name it is name or article in `LanguageId` language and for `ArticleId` article – Jessie Jan 01 '18 at 17:57
  • Is it correct to use two primary keys for intermediate table? Or better to use foreign keys? – Jessie Jan 01 '18 at 17:58
  • As I posted on my answer. You won't have "2 primary keys" you will have an only "composite" primary key on your intermediate table. And about to use it as foreign keys.. is a must have! – Art_Code Jan 01 '18 at 18:04
  • "composite" primary key can be (PK + PK) or (FK + FK) or (PK-FK + PK-FK)? – Jessie Jan 01 '18 at 18:20
  • Read my updated answer (as you changed your question title). "Composite" primary key can be "FK + FK" it can't be "PK + PK" because you can only have a primary key in a table. I mean you can have one hundred FK in a single table but you can only have 1 "PK" for that table. Maybe the right term you want to use is "unique" field. Then you can have "unique field + unique field" as a composite primary key. It can't be "PK-FK" either for the same reason i commented above. – Art_Code Jan 01 '18 at 18:44

2 Answers2

4

Link / Junction Tables

Assuming the linked tables are defined as:

CREATE TABLE Article
(
     ArticleId INT PRIMARY KEY
     -- ... other columns
);

CREATE TABLE Language
(
    LanguageId INT PRIMARY KEY
     -- ... other columns
);

As per @JulioPérez Option 1, the link table could be created as:

CREATE TABLE ArticleLanguage
(
    ArticleId INT NOT NULL,
    LanguageId INT NOT NULL,
    Name VARCHAR(50),

   -- i.e. Composite Primary Key, consisting of the two foreign keys.
   PRIMARY KEY(ArticleId, LanguageId),
   FOREIGN KEY(ArticleId) REFERENCES Article(ArticleId),
   FOREIGN KEY(LanguageId) REFERENCES Language(LanguageId)
);

i.e. with a composite primary key consisting of the two foreign keys used in the "link" relationship, and with no additional Surrogate Key (idArticleLanguage) at all.

Pros of this approach

  • Enforces uniqueness of the link, i.e. the same ArticleId and LanguageId cannot be linked more than once.
  • Saves an unnecessary additional surrogate key column on the link table.

Cons of this approach:

  • Any downstream tables which needs to reference this link table, would need to repeat both keys (ArticleId, LanguageId) as a composite foreign key, which would again consume space. Queries involving downstream tables which reference ArticleLanguage would also be able to join directly to Article and Language, potentially bypassing the link table (it is often easy to 'forget' that both keys are required in the join when using foreign composite keys).

SqlFiddle of option 1 here

The alternative (@JulioPérez Option 2), would be to to keep your additional surrogate PK on the reference table.

CREATE TABLE ArticleLanguage
(
    -- New Surrogate PK
    idArticleLanguage INT NOT NULL AUTO_INCREMENT,
    ArticleId INT NOT NULL,
    LanguageId INT,
    Name VARCHAR(50),

   PRIMARY KEY(idArticleLanguage),
   -- Can still optionally enforce uniqueness of the link
   UNIQUE(ArticleId, LanguageId),
   FOREIGN KEY(ArticleId) REFERENCES Article(ArticleId),
   FOREIGN KEY(LanguageId) REFERENCES Language(LanguageId)
);

Pros of this Approach

  • The Primary Key idArticleLanguage is narrower than the composite key, which will benefit any further downstream tables referencing table ArticleLanguage. It also requires downstream tables to join through the ArticleLanguage link table in order to get ArticleId and LanguageId, for further joins to the Language and Article tables.
  • The approach allows for an additional use case, viz that if it IS possible to add the same link to Language and Article more than once (e.g. two revisions or two reprints etc), then the UNIQUE key constraint can be removed

Cons of this Approach

  • If only one unique link per Article and Language is possible, then the additional surrogate key is redundant

SqlFiddle of option 2 here

If you're asking for an opinion, I would stick with option 1, unless you do require non-unique links in your ArticleLanguage table, or unless you have many further downstream tables which reference ArticleLanguage (this would be unusual, IMO).

Table per Type / per Class Inheritance

Unrelated to OP's post, but another common occurrence where a Foreign Key can be used as a Primary Key in the referencing table is when the Table per Type approach is taken when modelling an object oriented class hierarchy with multiple subclasses. Because of the 0/1 to 1 relationship between subclass and base class tables, the base class table's primary key can also be used as the primary key for the subclass tables, for instance:

CREATE TABLE Animal
(
   AnimalId INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
   -- Common Animal fields here
);

CREATE TABLE Shark
(
   AnimalId INT NOT NULL PRIMARY KEY, 
   -- Subclass specific columns
   NumberFins INT,
   FOREIGN KEY(AnimalId) REFERENCES Animal(AnimalId)
);

CREATE TABLE Ewok
(
   AnimalId INT NOT NULL PRIMARY KEY, 
   -- Subclass specific columns
   Fleas BOOL,
   FOREIGN KEY(AnimalId) REFERENCES Animal(AnimalId)
);

More on TPT and other OO modelling in tables here

StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • 2
    Thanks for helping me to answer the question with some practical examples. I am agree with @StuartLC. Option 1 is normally the most implemented solution nowadays. – Art_Code Jan 01 '18 at 18:53
  • So, what about when keys are PK+FK in the same time? – Jessie Jan 01 '18 at 19:13
  • 1
    @Jessie as per above Option 1, it's perfectly possible to use a combination of Composite Foreign Keys as Primary Keys in a LINK / UNION table like `ArticleLanguage`. There is one other common use of using a FK as a PK, and that's during table inheritance designs, i.e. where there are potentially multiple 'subclass' tables which are split into a table per class, but reuse the parent's Primary Key as a FK and PK in the subclass. [More reading here](https://stackoverflow.com/a/3579462/314291) – StuartLC Jan 01 '18 at 19:21
3

You have 2 ways:

1) Put "ArticleId + LanguageId" as your only primary key in "intermediate table" and you can name it as "idArticleLanguage". This is called a "composite" primary key because it is composed by 2 (in other case more than 2) fields, in this case 2 foreign keys (PK= FK + FK).

2) Create "idArticleLanguage" that has no relation to the other two "id" and set it as primary key.It can be a simple auto-increment integer.

Both alternatives are accepted. Your election will depend on the goal you want to achieve because what happens if you need to add in this intermediate table the same Article with the same language (Wilkommen German for example) because you have 2 different editions of the article? if you choose alternative 1 it will throw an error because you will have the same composite primary key for 2 rows then you must choose alternative 2 and create a completely different primary key for this table

In any other case (or purpose) you can choose alternative 1 and it will work perfectly

About the change of your question title:

When use foreign key as primary key in the same time?

I will explain it with this example:

You have 2 tables: "country" and "city". "country" have all the countries of the world, "city" have all the cities of the world. But you need to know every capital in the world. What you should do?

You must create an "intermediate table" (named as "capital") that will have every capital on the world. So, we know that country have it's primary key "idcountry" and city have it's primary key is "idcity" you need to bring both as foreign keys to the table "capital" because you will need data of "city" and "country" tables to fill "capital" table

Then "capital" will have it's own primary key "idcapital" that can be a composite one "idcity+idcountry" or it can be an auto-increment integer in both cases you must have "idcity" and "idcountry" as foreign keys on your "capital" table.

Art_Code
  • 518
  • 4
  • 12
  • `2) Create "idArticleLanguage" that has no relation to the other two "id" and set it as primary key. You already have` maybe you meant as foreign keys? – Jessie Jan 01 '18 at 17:43
  • sorry i will update my answer. I was about to write more xD! I will eliminate "you already have". I thought I deleted it. Thanks @Jessie – Art_Code Jan 01 '18 at 17:52
  • I think you are wrong again. You wanted to say use two primary keys in intermediate table as complicated key. Or use two foreign keys. Both are approaches are right. But I am not sure – Jessie Jan 01 '18 at 18:02
  • I mean you can create "idArticleLanguage" as the primary key of the table ArticleLanguage but that doesn't mean ""idArticleLanguage" must contain "idArticle + idlanguage", it can be just an integer with auto-increment for example or it can be "idArticle + idlanguage" both are perfectly right – Art_Code Jan 01 '18 at 18:07