Can foreign key become primary key?

Asked

Viewed 15,597 times

8

exemplifying, I have two tables: customer and contact.

The contact table contains the customer’s phone column as primary key, fax column and e-mail column.
The client table contains the customer’s phone column as primary key and foreign key and the name column.

+-------------------------------+      +--------------------------------------------+
| contato                       |      | cliente                                    |
+-------------------------------+      +--------------------------------------------+
| telefoneCliente (primary key) |      | telefoneCliente (primary key, foreign key) |
| fax                           |      | nome                                       |
| email                         |      |                                            |
+-------------------------------+      +--------------------------------------------+

First: this can happen without creating inconsistency?
Second: is there any way that the value of a primary key is the same as the value of a primary key of another table?

  • 1

    "Is there any way that the value of a primary key is the same value as a primary key of another table?" If the primary key of one is also foreign key in the primary key of the other, then that is exactly what will happen; the values will necessarily be the same (assuming for each row in the table contato you add after a row in the table cliente).

4 answers

14


First, answers to your questions:

P: This can happen without creating inconsistency?

A: In the current structure this model allows data inconsistency (one telefone without Cliente, for example).

P: there is some way the value of a primary key is the same value of a primary key of another table?

R: Yes, but in very specific cases. If you have an identifier in two tables with the same value, for all practical purposes you are identifying the same entity; in this case, why not have only one table?

We will initially analyze your data model. If I understood correctly, this would be a representation:

inserir a descrição da imagem aqui

According to this model, a contact is identified by a telephone, and this is used to uniquely identify a Customer.

Problems with this model:

  • What happens if a customer owns 2 or more phones?
  • What happens if a customer has email, but doesn’t call?
  • What happens if 2 customers share the same phone number?

Your model needs to be abstract enough to cover as many trivial situations as possible. Another aspect is the definition of the primary key: a value (or, alternatively, values) that does not repeat itself and uniquely identifies a record in its table. Neither phone nor name cover this spec.

Step 1: The creation of a field ID for exclusive identification of the registration.

inserir a descrição da imagem aqui

Create a field specifically with single initialization (a numerical autocomperer or GUID, for example) which will serve as the unique identifier of the record. Create a field in your table contato, Cliente_ID, and use it as a foreign key.

This way you allow homonyms (who will have different Ids) and repeat phones, without violating your model.

But it’s still not good enough.

Step 2: Modeling of contacts by type

inserir a descrição da imagem aqui

Create a table, contact type, and store all the contact types you need there. For example:

Contato_Tipo
ID  Descricao
1   Telefone
2   Fax
3   Email

Modify your table Contato to, instead of storing a value of each type, now reference the field ID table Contato_Tipo via the foreign key Contato_Tipo_ID. Store a single value there in the column Valor.

We will simulate a Client, Goku. Your phone number is 555-4433, and your email is [email protected]. The values in the tables would be as follows:

Cliente
ID    Nome
1     Goku

Contato
ID    Cliente_ID    Contato_Tipo_ID   Valor
1     1             1                 555-4433
2     1             3                 [email protected]

This model has great advantages over the previous one. It allows 0-N values of 0-N types for each client; and when the need to add one more contact type appears (Stackoverflow profile link for example), you don’t need to change its structure - just add one more record to the table Contato_Tipo.

  • Yes, but in this case, I would like to use the phone itself as a primary key, if the customer has more than one phone, I think I could use as a concatenated key.

  • Nothing stops you from using the phone. However, consider that you may be violating the entity scope - a Telephone entity is identifying a Customer entity. Doesn’t sound strange to you?

  • Maybe, but depending on your point of view, I chose phone because it’s a relatively unique data.

  • 3

    @Onosendai: Identifying a customer by phone is not necessarily wrong (for example, Whatsapp does just that). On the other hand, this only makes sense if the customer can only have a single phone - putting more than one value in a single row of the table is asking to give shit (for example, if we represent up pair of phones as "A|B" we will not realize that it is the same set of "B|A" or that it is a phone that also occurs in "A")

  • As I mentioned, @missingno, nothing stops you from using the phone. But situations where a phone uniquely identifies an entity are very rare (Whatsapp being the exception that confirms the rule, and that actually uses the phone as an ID). Even phone companies identify users primarily, and associate N phones with these.

  • @Patrick, the keyword in your sentence is 'relatively'. And when not? What do you see as the ideal solution?

  • When it is not, I will modify the program so that it fits in the bank. Using this type of identification is much simpler.

  • @Onosendai, I don’t know if I’m wrong, but in the first image, the foreign key wouldn’t be on the contact table?

  • @Patrick I read your question again, and you are correct - I reversed the connection on the first chart. Thank you! I will fix it now.

  • 1

    @Patrick: I don’t understand how the concatenated key concept can be useful in the problem described in your question.

  • 1

    @Patrick on program modification, the modeling decision is obviously yours - but I would say it’s always better to create a more robust model at the beginning that costs little future maintenance effort than a simple model that implies refactoring radical.

  • @Onosendai, now I realized the answer of the first question, about inconsistency: phone without client, would not be solved just by placing the column "name" as not null?

  • @user2478690, ignore what I said, I traveled.

Show 8 more comments

3

There is no problem the key of a table also being a foreign key. These concepts are independent of each other.

The concept of key and primary key serves to restrict the values between rows of a table. Two rows of a table cannot have the same values in the columns of a key.

On the other hand, the foreign key restricts the values in a column to only those in the table.

In your example, the foreign key restriction means that we can only insert customers who have had their phone and fax inserted into the contact table. Also, primary key restriction means we can’t have two customers sharing the same phone.

  • So there is no inconsistency? As for creating a concatenated/composite key with a foreign key, it is possible?

  • Theoretically, the key referenced by the foreign key constraint can be any type of key. However, some databases such as sqlite and mysql may not support all foreign key types in the default settings. See the BD documentation you’re using.

3

Colleagues have already explained the question perfectly, but I would like to add with a practical example that shows how this situation (foreign and primary key) beyond possible is very useful.

Let’s think about a Product table that receives products from several companies. It may suffer from the fact that different products may have the same id (each company has registered its products with their ids). Updates, for example, would mess everything up. To solve, we can place the idDaEmpresa column on the Product, make it a primary key and a foreingkey to the company table. Product.idDaEmpresa <--> Company.id

CREATE TABLE Produto (
id INTEGER NOT NULL,
descricao VARCHAR (255) NOT NULL,
idDaEmpresa INTEGER NOT NULL REFERENCES Empresa(id),
CONSTRAINT pkProduto PRIMARY KEY (id, idDaEmpresa)
)
  • "id" would be the code of the other company in a table and "idDaEmpresa" would be the code of the company in question in another table?

  • i would be the product code, and idDaEmpresa would be the company table id. The idea is that we could have several products with the same id, but never two products with the same id.

2

I agree with the colleagues who confirmed above that there is no inconsistency. It is perfectly possible and logical - and I say more, it should be put! In doubt always apply the foreign key.

Let’s take the example of a user entity that specializes in a natural or legal person. The primary key of the user entity must be the same for specializations. I can not put another key and nor work with key composition, because it would allow the duplicate records with the same key of the table users. Ex: if the key of the table users was Cpf and there was a composite key in the specializations, such as an integer and auto incrementable id and Cpf itself, there could be population without errors (by the bank) of the same Cpf in other tuples for both specializations, which would be a logical error. Because there is only one Cpf for each user.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.