ALTER TABLE per aggiungere una chiave primaria composita


195

Ho un tavolo chiamato provider. Ho tre colonne denominate person, place, thing. Possono esserci persone duplicate, luoghi duplicati e cose duplicate, ma non può mai esserci una duplice combinazione persona-luogo-cosa.

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

Risposte:


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

Se esiste già una chiave primaria, si desidera farlo

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

17
@ David542 No, non è possibile: puoi avere solo 1 chiave primaria.
Adrian Cornish,

35
@ David: è una singola chiave primaria composta da più campi, ovvero una chiave composita.
Marc B,

3
@ David542 Certo che puoi - questa è una chiave primaria composita composta da 3 campi. La combinazione dei 3 campi deve essere unica.
Adrian Cornish,

2
grazie per la pubblicazione - mi ha fatto davvero uscire dalle battaglie con l'
Ui

1
una delle risposte più preziose in SO :)
alwbtc

21

La risposta di @Adrian Cornish è corretta. Tuttavia, c'è un altro avvertimento nel rilasciare una chiave primaria esistente. Se quella chiave primaria viene utilizzata come chiave esterna da un'altra tabella, verrà visualizzato un errore quando si tenta di rilasciarla. In alcune versioni di mysql il messaggio di errore era errato (a partire dalla 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 vuoi rilasciare una chiave primaria a cui fa riferimento un'altra tabella, dovrai prima rilasciare la chiave esterna in quell'altra tabella. È possibile ricreare quella chiave esterna se la si desidera ancora dopo aver ricreato la chiave primaria.

Inoltre, quando si utilizzano chiavi composite, 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 la stessa cosa. Entrambi impongono l'univocità su quell'insieme di tre campi, tuttavia dal punto di vista dell'indicizzazione c'è una differenza. I campi sono indicizzati da sinistra a destra. Ad esempio, considerare le seguenti query:

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 nell'istruzione ALTER 1
A può usare l'indice della chiave primaria nell'istruzione ALTER 2
C può usare entrambi gli indici
D non può usare nessuno degli indici

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

D non può usare nessuno dei due indici perché non conosce la persona.

Vedi i documenti mysql qui per maggiori informazioni.


@Tutti - Potresti condividere lo stesso JPA equivalente per lo stesso?
Pra_A

17

Potresti semplicemente voler un VINCITORE UNICO. Soprattutto se hai già una chiave surrogata. (esempio di una chiave surrogata già esistente sarebbe una singola colonna che è un AUTO_INCREMENT)

Di seguito è riportato il codice sql per un vincolo univoco

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

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

In genere utilizzo una chiave surrogata ...... quindi aggiungo un vincolo univoco. In questo modo .... se l '"unicità" cambia lungo la strada, non è molto drammatico modificare il vincolo, rispetto al pasticciare con la chiave primaria. E se hai tabelle figlio a cui la chiave esterna fa riferimento a questa tabella, devi solo trovare la chiave surrogata, non tutte e 3 le colonne. -
granadaCoder


1

È sicuramente meglio usare COMPOSITE UNIQUE KEY, come offerto da @GranadaCoder, un esempio un po 'complicato:

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


0

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

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.