2012-01-14 17 views
155

Ho una tabella denominata provider. Ho tre colonne chiamate person, place, thing. Possono esserci persone duplicate, luoghi duplicati e cose duplicate, ma non può mai esserci una combinazione di persona-luogo-cosa.ALTER TABLE per aggiungere una chiave primaria composita

Come farei ALTER TABLE per aggiungere una chiave primaria composita per questa tabella in MySQL con queste tre colonne?

risposta

340
ALTER TABLE provider ADD PRIMARY KEY(person,place,thing); 

Se una chiave primaria esiste già allora si vuole fare questo

ALTER TABLE provider DROP PRIMARY KEY, ADD PRIMARY KEY(person, place, thing); 
+2

Questo aggiunge tre pks unico, non una pk composito. – David542

+13

@ David542 No, non si può avere solo 1 chiave primaria. –

+28

@David: è una singola chiave primaria composta da più campi, ovvero una chiave composta. –

14

Si può semplicemente voler un vincolo univoco. Soprattutto se hai già una chiave surrogata. (esempio: un AUTO_INCREMENT) La risposta di

ALTER TABLE `MyDatabase`.`Provider` 
    ADD CONSTRAINT CK_Per_Place_Thing_Unique UNIQUE (person,place,thing) 
; 
+0

Grazie, un vincolo è quello che volevo, non sapevo cosa chiedere in questo post iniziale. Grazie per aver aggiunto questo alla discussione. – ZaneDarken

+0

Generalmente uso una chiave surrogata ...... quindi aggiungo un vincolo univoco. In questo modo ... se la "unicità" cambia lungo la strada, non è molto drammatico modificare il vincolo, a differenza della chiave primaria. E se hai tabelle figlio che la chiave esterna fa riferimento a questa tabella, devi solo FK la chiave surrogata, non tutte e 3 le colonne. - – granadaCoder

3
alter table table_name add primary key (col_name1, col_name2); 
0

ALTER TABLE table_name DROP PRIMARY KEY,ADD PRIMARY KEY (col_name1, col_name2);

16

@Adrian Cornish è corretta. Tuttavia, vi è un altro avvertimento per eliminare una chiave primaria esistente. Se la chiave primaria viene utilizzata come chiave esterna da un'altra tabella, si verificherà un errore quando si tenta di rilasciarlo. In alcune versioni di MySQL il messaggio di errore c'era malformati (come del 5.5.17, questo messaggio di errore è ancora

alter table parent drop column id; 
ERROR 1025 (HY000): Error on rename of 
'./test/#sql-a04_b' to './test/parent' (errno: 150). 

Se si vuole far cadere una chiave primaria che viene riferito da un altro tavolo, si dovrà far cadere la chiave esterna in questo altro tavolo prima. è possibile ricreare quella chiave esterna se si vuole ancora dopo si ricrea la chiave primaria.

Inoltre, quando si utilizza chiavi composte, l'ordine è importante. Questi

1) ALTER TABLE provider ADD PRIMARY KEY(person,place,thing); 
and 
2) ALTER TABLE provider ADD PRIMARY KEY(person,thing,place); 

non sono il stessa cosa. Entrambi fanno rispettare l'unicità su quel set di tre campi, tuttavia da un punto di vista dell'indicizzazione c'è una differenza. I campi sono indicizzati da sinistra a destra. Ad esempio, considerare le seguenti domande:

A) SELECT person, place, thing FROM provider WHERE person = 'foo' AND thing = 'bar'; 
B) SELECT person, place, thing FROM provider WHERE person = 'foo' AND place = 'baz'; 
C) SELECT person, place, thing FROM provider WHERE person = 'foo' AND place = 'baz' AND thing = 'bar'; 
D) SELECT person, place, thing FROM provider WHERE place = 'baz' AND thing = 'bar'; 

B può usare l'indice della chiave primaria ALTER 1
A può utilizzare l'indice chiave primaria ALTER 2
C può utilizzare sia indice
D non è possibile utilizzare né l'indice

A utilizza i primi due campi dell'indice 2 come indice parziale. A non può usare l'indice 1 perché non conosce la porzione intermedia dell'indice. Potrebbe comunque essere in grado di utilizzare un indice parziale solo per persona.

D non può utilizzare alcun indice perché non conosce la persona.

Vedere i documenti mysql here per ulteriori informazioni.

1

`s sicuramente meglio utilizzare COMPOSITE UNIQUE KEY, come offerto @GranadaCoder, un piccolo esempio po 'complicato però:

ALTER IGNORE TABLE table_name ADD UNIQUES INDEX idx_name(some_id, another_id, one_more_id);

Problemi correlati