2009-04-26 4 views
13

Supponiamo di avere una tabella molti-molti tra artisti e fan. Quando si tratta di progettare il tavolo, si fa a progettare la tavola come tale:SQL: hai bisogno di una chiave primaria auto-incrementale per le tabelle Many-Many?

ArtistFans 
    ArtistFanID (PK) 
    ArtistID (FK) 
    UserID (FK) 

(ArtistID and UserID will then be contrained with a Unique Constraint 
    to prevent duplicate data) 

O si fa a costruire utilizzare un PK composti per i due campi rilevanti:

ArtistFans 
    ArtistID (PK) 
    UserID (PK) 

(The need for the separate unique constraint is removed because of the 
compound PK) 

Are ci sono qualche vantaggio (magari indicizzazione?) per usare lo schema precedente?

risposta

18
ArtistFans 
    ArtistID (PK) 
    UserID (PK) 

L'uso di un PK incrementale automatico non ha alcun vantaggio qui, anche se le tabelle padre li hanno.

Vorrei anche creare automaticamente un indice "reverse PK" su (UserID, ArtistID): ne avrete bisogno perché interrogherete la tabella per entrambe le colonne.

Le colonne numero di identificazione/ID hanno il loro posto. Li sceglieresti per migliorare alcune cose dopo il processo di normalizzazione basato sulla piattaforma fisica. Ma non per tabelle di collegamento: se il vostro braindead ORM insiste, quindi modificare ORM ...

Modifica, Oct 2012

E 'importante notare che avresti ancora bisogno unici (UserID, ArtistID) e (ArtistID, UserID) indici. L'aggiunta di incrementi automatici utilizza solo più spazio (in memoria, non solo su disco) che non dovrebbe essere utilizzato

+0

Una chiave primaria è solo un tipo speciale di indice. Un indice che duplica la chiave primaria aggiunge solo un sovraccarico. – Andomar

+0

L'ordine è importante: questo è un indice diverso – gbn

+0

Ah ok, ha senso quindi :) – Andomar

2

Non riesco a pensare ad alcun motivo per utilizzare il primo modulo che elencherai. La chiave primaria composta va bene, e avendo una chiave primaria separata e artificiale (insieme alla contraint unica che è necessaria sulle chiavi esterne) ci vorrà solo più tempo per calcolare e spazio per memorizzare.

1

Il metodo standard consiste nell'utilizzare la chiave primaria composita. Aggiungere una chiave di autoincremento separata significa semplicemente creare un sostituto che è già lì usando quello che hai. Corretti schemi di normalizzazione del database guarderebbero in basso usando l'autoincrement.

5

Anche se si crea una colonna Identity, non deve essere la chiave primaria.

ArtistFans 
    ArtistFanId 
    ArtistId (PK) 
    UserId (PK) 

colonne identità può essere utile mettere in relazione questo rapporto ad altri rapporti. Ad esempio, se c'era una tabella dei creatori che specificava la persona che creava la relazione artista-utente, poteva avere una chiave esterna su ArtistFanId, invece della chiave primaria composita ArtistId + UserId.

Inoltre, le colonne Identity sono necessarie (o migliorano notevolmente il funzionamento di) alcuni pacchetti ORM.

+0

Ciò significa che per trovare i dettagli del creatore-artista devi * sempre * includere la tabella ArtistFans nella JOIN = più lenta. – gbn

+0

In questo caso, sembra improbabile che tu sia interessato al creatore della relazione artista-utente, ma non all'utente. – Andomar

0

Divertente come tutte le risposte favorire la variante 2, quindi devo dissentire e sostenere per la variante 1;)

Per rispondere alla domanda nel titolo: no, non hai bisogno di esso. Ma ...

Avere una colonna di auto-incrementale o identità ogni tabella semplifica il modello di dati in modo che si sa che ognuno dei vostri tavoli ha sempre una singola colonna PK.

Di conseguenza, ogni relazione (chiave esterna) da una tabella a un'altra è sempre composta da una singola colonna per ogni tabella.

Inoltre, se ti capita di scrivere un framework di applicazioni per moduli, elenchi, report, registrazione ecc., Devi solo trattare le tabelle con una singola colonna PK, che semplifica la complessità del tuo framework.

Inoltre, una colonna PK id aggiuntiva non ti costa molto in termini di spazio su disco (tranne che per le tabelle miliardi-record-plus).

Naturalmente, ho bisogno di menzionare uno svantaggio: in una relazione nonni-genitore-figlio, il bambino perderà le informazioni sui nonni e richiederà un JOIN per recuperarlo.

+0

...e un sacco di indici univoci (vincoli unici sono anche indici sul disco) per garantire l'integrità dei dati della tua chiave naturale ... – gbn

+0

Non sono d'accordo sul fatto che l'aggiunta di una colonna in più rende le cose più semplici. E l'utilizzo di una chiave surrogata di incremento automatico al posto del PK naturale rende l'integrità dei dati più debole, a meno che non si aggiunga il vincolo extra, come commentato da devio. Se hai fatto bene la tua analisi, le tabelle delle entità avranno un PK semplice, mentre le tabelle delle relazioni avranno un PK composto. Cosa potrebbe essere più semplice? –

5

Supponendo che tu sia già un devoto della chiave surrogata (sei in buona compagnia), c'è un caso da fare per andare fino in fondo.

Un punto chiave a volte dimenticato è che le relazioni stesse possono avere proprietà. Spesso non è sufficiente affermare che due cose sono correlate; potresti dover descrivere la natura di quella relazione. In altre parole, non c'è nulla di speciale in una tabella delle relazioni che dice che può avere solo due colonne.

Se non c'è niente di speciale in queste tabelle, perché non trattarlo come ogni altra tabella e utilizzare una chiave surrogata? Se finisci per dover aggiungere proprietà alla tabella, ringrazierai i tuoi fortunati livelli di presentazione che non devi passare attorno a una chiave composta solo per modificare tali proprietà.

Non lo chiamerei nemmeno una regola empirica, più un qualcosa da considerare. Nella mia esperienza, alcune strette relazioni finiscono per trasportare dati aggiuntivi, diventando essenzialmente entità in se stesse, degne di una chiave surrogata.

Il problema è che l'aggiunta di queste chiavi dopo il fatto può essere un dolore. Se il costo della colonna e dell'indice aggiuntivi valga il valore di prevenire questo mal di testa, ciò dipende in realtà dal progetto.

Per quanto mi riguarda, una volta morso, due volte timido - Vado per la chiave surrogata fuori dal cancello.

+0

Ti ringrazio davvero per questo commento. Mi sono sentito così solo su questo. Sono completamente d'accordo con la tua argomentazione. – Thiezar

0

A mio parere, nella colonna ID SQL puro non è necessario e non deve essere utilizzato. Ma per i framework ORM come Hibernate, la gestione delle relazioni molti-a-molti non è semplice con le chiavi composte ecc., Specialmente se le tabelle di join hanno colonne aggiuntive.

Quindi, se ho intenzione di utilizzare un framework ORM sul db, preferisco mettere una colonna id di incremento automatico a quella tabella e un vincolo univoco alle colonne di riferimento insieme. E, naturalmente, un vincolo non nullo se richiesto.

Quindi considero la tabella come qualsiasi altra tabella nel mio progetto.

Problemi correlati