Come creare correttamente chiavi primarie composite - MYSQL


182

Ecco una grossolana semplificazione di un intenso setup con cui sto lavorando. table_1ed table_2entrambi hanno chiavi primarie surrogate con incremento automatico come ID. infoè una tabella che contiene informazioni su entrambi table_1e table_2.

table_1 (id, field)  
table_2 (id, field, field)
info ( ???, field)

Sto cercando di decidere se devo creare la chiave primaria di infoun composito degli ID da table_1e table_2. Se dovessi farlo, quale di questi ha più senso?
(in questo esempio sto combinando ID 11209 con ID 437)

INT(9)11209437 (posso immaginare perché questo è negativo)
VARCHAR (10) 11209-437
DECIMAL (10,4)11209.437

O qualcos'altro?

Andrebbe bene usarlo come chiave primaria su un DB MYYSAM MYSQL?


Risposte:


343

Vorrei usare una chiave composita (multi-colonna).

CREATE TABLE INFO (
    t1ID INT,
    t2ID INT,
    PRIMARY KEY (t1ID, t2ID)
) 

In questo modo è possibile avere t1ID e t2ID come chiavi esterne che puntano anche alle rispettive tabelle.


2
Oh wow, è così che crei una chiave composita! sembra che io abbia completamente frainteso il concetto. Grazie!! Quindi qualcosa di simile è interamente a scopo di indicizzazione, quindi corretto? Dato che non sarei in grado di fare riferimento a un disco usando questo composito, dovrei comunque fare un UPDATE info ... WHERE t1ID=11209 AND t2ID=437?
filip

2
corretta. Sebbene poiché entrambe le colonne dovrebbero essere univoche, dove t1ID = 11209 sarebbe probabilmente sufficiente.
AlexCuse,

39
@AlexCuse la combinazione di entrambe le colonne è unica, ma per t1ID = 11209 può esserci un numero qualsiasi di t2ID.
e18r,

21

Non farei della chiave primaria della tabella "info" un composto dei due valori di altre tabelle.

Altri possono articolare meglio le ragioni, ma sembra sbagliato avere una colonna che è davvero composta da due informazioni. Cosa succede se si desidera ordinare l'ID dalla seconda tabella per qualche motivo? Cosa succede se si desidera contare il numero di volte in cui è presente un valore di una delle tabelle?

Le terrei sempre come due colonne distinte. È possibile utilizzare una chiave primay a due colonne in mysql ... PRIMARY KEY (id_a, id_b) ... ma preferisco utilizzare un indice univoco a due colonne e avere un campo chiave primaria con incremento automatico.


1
Hai assolutamente ragione sul mantenere colonne distinte. Non ero a conoscenza del fatto che potresti avere un indice univoco a due colonne e penso che in realtà potrebbe essere una buona opzione per me. Potrei chiederti perché preferiresti comunque mantenere la chiave primaria come auto-incremento?
filip

3
Non ho ragioni davvero convincenti e ammetto che questo è un punto di contesa tra me e alcuni dei miei colleghi, perché è più economico avere meno colonne. Trovo più facile scrivere join su una singola chiave esterna. A volte il significato di queste tabelle "Mapping tra due tabelle" diventa importante quanto le tabelle originali e la sua chiave primaria diventa una colonna di chiave esterna in altre tabelle.
mercoledì

grazie. Penso che il tuo detto abbia molto senso e lo proverò come un indice univoco a due colonne + chiave primaria con incremento automatico
filip

1
Immagino che una ragione dalla cima della mia testa sia che vuoi creare una tabella delle relazioni. hai tre tabelle, ad esempio marketplace, currency e provider, un provider può esistere SOLO in un marketplace UNA VOLTA, quindi la tua tabella delle relazioni può fornire solo una singola valuta, quindi avresti composto (id_market, id_provider) il che significa che puoi solo fare quella connessione una volta, tentando di aggiungere nuovamente lo stesso mercato e provider insieme fallirà, il che significa che sono unici, quindi avresti una seconda colonna, diciamo id_currency, il che significa che la valuta è singolare nell'intera tabella, ha senso?
Christopher Thomas,

1
Per tutti coloro che vedranno questo thread in seguito, tieni presente che il motivo per cui questa è una cattiva pratica è perché viola un principio molto basilare di progettazione del database. La prima forma normale richiede che ogni informazione abbia la sua colonna. Non vi è praticamente alcun motivo per violare questo e molteplici vantaggi nella normalizzazione della struttura del database.
smcjones,

15

la sintassi è CONSTRAINT constraint_name PRIMARY KEY(col1,col2,col3)ad esempio:

CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

l'esempio sopra funzionerà se lo stai scrivendo mentre crei la tabella per esempio ::

CREATE TABLE person (
   P_Id int ,
   ............,
   ............,
   CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
);

per aggiungere questo vincolo a una tabella esistente è necessario seguire la sintassi seguente

ALTER TABLE table_name ADD CONSTRAINT constraint_name PRIMARY KEY (P_Id,LastName)

8

Supponiamo che tu abbia già creato una tabella ora puoi usare questa query per creare una chiave primaria composita

alter table employee add primary key(emp_id,emp_name);

5

A parte le preferenze di progettazione personale, ci sono casi in cui si desidera utilizzare chiavi primarie composite. Le tabelle possono avere due o più campi che forniscono una combinazione unica e non necessariamente tramite chiavi esterne.

Ad esempio, ogni stato degli Stati Uniti ha una serie di distretti congressuali unici. Mentre molti stati possono avere singolarmente un CD-5, non ci sarà mai più di un CD-5 in nessuno dei 50 stati e viceversa. Pertanto, la creazione di un campo autonumber per il CD-5 del Massachusetts sarebbe ridondante.

Se il database gestisce una pagina Web dinamica, scrivere codice per eseguire query su una combinazione a due campi potrebbe essere molto più semplice dell'estrazione / reinvio di una chiave numerata automaticamente.

Quindi, mentre non rispondo alla domanda originale, apprezzo sicuramente la risposta diretta di Adam.


4

Le chiavi primarie composite sono ciò che vuoi dove vuoi creare una relazione da molte a molte con una tabella dei fatti. Ad esempio, potresti avere un pacchetto di affitto vacanze che include un numero di proprietà al suo interno. D'altra parte, la proprietà potrebbe anche essere disponibile come parte di una serie di pacchetti di noleggio, da soli o con altre proprietà. In questo scenario, si stabilisce la relazione tra la proprietà e il pacchetto di noleggio con una tabella dei fatti della proprietà / pacchetto. L'associazione tra una proprietà e un pacchetto sarà univoca, ti unirai sempre e solo usando property_id con la tabella delle proprietà e / o package_id con la tabella dei pacchetti. Ogni relazione è unica e una chiave auto_increment è ridondante in quanto non verrà visualizzata in nessun'altra tabella. Quindi definire la chiave composita è la risposta.


1
CREATE  TABLE `mom`.`sec_subsection` (

  `idsec_sub` INT(11) NOT NULL ,

  `idSubSections` INT(11) NOT NULL ,

  PRIMARY KEY (`idsec_sub`, `idSubSections`) 

);

1

@AlexCuse Volevo aggiungere questo come commento alla tua risposta, ma ho rinunciato dopo aver fatto più tentativi falliti di aggiungere nuove righe nei commenti.

Detto questo, t1ID è unico nella tabella_1 ma ciò non lo rende unico anche nella tabella INFO.

Per esempio:

La tabella_1 ha:
campo ID
1 A
2 B

Table_2 ha:
campo ID
1 X
2 Y

INFO può quindi avere:
t1ID t2ID campo
1 1 alcuni
1 2 dati
2 1 in ogni
2 2 righe

Quindi nella tabella INFO per identificare in modo univoco una riga sono necessari sia t1ID che t2ID


si chiama chiave composita
Pavel P

1
@PavelP la mia risposta è il commento di Alex "Anche se entrambe le colonne dovrebbero essere uniche, dove t1ID = 11209 sarebbe probabilmente sufficiente." ... Sono d'accordo che l'uso della chiave composita sia corretto ma per identificare la corrispondenza esatta avrai bisogno sia di t1ID che di t2ID ... Spero sia chiaro ora.
sacro il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.