Devo usare chiavi primarie a più colonne o aggiungere una nuova colonna?


15

Il mio attuale progetto di database utilizza una chiave primaria a più colonne per utilizzare i dati esistenti (che sarebbero comunque unici) invece di creare una colonna aggiuntiva che assegna a ciascuna voce una chiave arbitraria. So che questo è permesso, ma mi chiedevo se questa è una pratica che potrei voler usare con cautela ed eventualmente evitare (proprio come andare in C).

Quindi quali sono alcuni degli svantaggi che potrei vedere in questo approccio o perché potrei volere una chiave a colonna singola?


2
Non so, penso che sarebbe stato meglio su SO.
FrustratedWithFormsDesigner,

2
@FrustratedWithFormsDesigner Potrebbe andare su SO, ma penso che funzioni anche qui, poiché il focus della domanda sembra essere il "cosa sono i pro e i contro di questo approccio" piuttosto che "come faccio X?".
Adam Lear

@Anna Lear ♦: è un "pro e contro" sulle decisioni di progettazione che avrà un impatto diretto e definito sulla codifica, quindi penso che SO sarebbe un posto migliore.
FrustratedWithFormsDesigner

Risposte:


8

Di solito, quando si dispone di una tabella con una chiave primaria multi-colonna, è il risultato di una tabella di join (molti-a-molti) che diventa elevata come propria entità (e quindi merita la propria chiave primaria). Ci sono molti che sostengono che qualsiasi tabella di join DOVREBBE essere un'entità per impostazione predefinita, ma questa è una discussione per un altro giorno.

Diamo un'occhiata a un'ipotetica relazione da molte a molte:

Studente * --- * Classe

(uno studente può essere in più classi, una classe può avere più studenti).

Tra queste due tabelle ci sarà una tabella di giunzione chiamata StudentClass (o ClassStudent a seconda di come la scrivi). A volte, vuoi tenere traccia di cose come quando lo studente era in classe. Quindi lo aggiungerai alla tabella StudentClass. A questo punto, StudentClass è diventato un'entità unica ... e dovrebbe essere assegnato un nome per riconoscerlo come tale, ad esempio Iscrizione.

Studente 1 --- * Iscrizione * --- 1 lezione

(uno studente può avere molte iscrizioni, ogni iscrizione è per una classe (o andando nel modo opposto una classe può avere molte iscrizioni, ogni iscrizione è per uno studente).

Ora puoi fare domande su quanti studenti sono stati iscritti alla classe Chemistry 101 l'anno scorso? O in quali classi era iscritto lo studente John Doe mentre frequentava la Acme University? Ciò era possibile senza la chiave primaria separata, ma una volta che si dispone di una chiave primaria per l'iscrizione, una domanda più semplice sarebbe di queste iscrizioni (per ID), quanti studenti hanno ricevuto un voto di passaggio?

La determinazione del fatto che un'entità meriti un PK si riduce a quanta query (o manipolazione) farai per quell'entità. Diciamo ad esempio che volevi allegare i compiti completati per uno studente in una classe. Il luogo logico in cui allegare questa entità (Assegnazione) sarebbe sull'entità Iscrizione. Dare la registrazione alla propria chiave primaria renderebbe più semplici le query di assegnazione.


1
Quindi lo aggiungerai alla tabella StudentClass. A questo punto, StudentClass è diventato un'entità unica ... e dovrebbe essere assegnato un nome per riconoscerlo come tale, ad esempio Iscrizione. È una cosa così semplice, ma ha così tanto valore nel farlo!
Botis,

8

Ha senso avere una colonna id separata. Quando vuoi ottenere qualcosa dalla tabella del tuo database, è più facile fare:

SELECT whatever FROM table WHERE id=13

di SELEZIONA qualunque cosa DALLA tabella DOVE col1 = 'val1' AND col2 = 'val2' AND col3 = 'val3'

Ad esempio, in un'applicazione Web si traduce in un URL simile al seguente:

www.somewebsite.com/somepage.php?id=13

o in questo modo:

www.somewebsite.com/somepage.php?col1=val1&col2=val2&col3=val3

4
Ed è molto più semplice aggiungere una tabella correlata quando è possibile collegarsi a un ID, anziché a più colonne
CaffGeek,

3
Scusa, a questo punto devo -1, come A) non è in bianco e nero. L'aggiunta di una colonna ID comporta negativi come dove e quando si genera quel nuovo ID. Inoltre, potrebbe comportare ulteriori join o SELECTquery. E, B) , non ho idea di come questo effettivamente causi qualsiasi tipo di requisito URL (a meno che tu non stia lavorando con un framework non valido). I miei URL non contengono stringhe di query ?id=13, figuriamoci ?col1=val1&col2=val2&col3=val3.
Nicole,

2
@renesis: questo sito ha domande e utenti unici, che si trovano negli URL. Tuttavia, questo è in qualche modo un caso speciale, poiché quei dati particolari non cambiano.
Michael K,

1
@Renesis, la maggior parte (forse tutti) i db moderni hanno tipi di colonna integer auto_increment che possono generare gli ID automaticamente e in modo sicuro e riportarli tramite query sql o chiamate di funzione della libreria. O in un ambiente distribuito, usi un grande hash casuale. Alcuni DB creeranno anche una colonna id nascosta per te se non ne hai già una nella tabella.
GrandmasterB,

@Michael - Non ho detto che gli ID non siano mai negli URL. Certo che lo sono. Se hai URL che rappresentano una riga di dati, sì, probabilmente quei dati dovrebbero avere un ID univoco. A meno che qualche altra parte dell'URL non fornisca già le altre parti della chiave multipla. @GrandmasterB Nessuna delle ultime due società per cui ho lavorato (per oltre 6 anni), che utilizzano entrambi MySQL (uno supportava anche Oracle e SQL Server) è stata in grado di utilizzare l'auto-incremento, né un grande hash casuale.
Nicole,

8

Fondamentalmente ti stai chiedendo se dovresti usare chiavi surrogate o naturali (nel tuo caso suona come chiavi naturali composite ). Ecco un ottimo articolo: http://www.agiledata.org/essays/keys.html

Preferisco le chiavi surrogate perché semplificano l'amministrazione durante la vita del DB (non devi mai preoccuparti dell'implicazione delle chiavi che cambiano significato, cosa che non dovrebbe mai accadere ma succede in qualsiasi sistema reale in cui sono coinvolti gli umani). Tuttavia , se nel DB sono presenti molte tabelle di "ricerca" (ovvero tabelle che sono sostanzialmente chiavi: coppie di valori), le chiavi surrogate possono risultare ingombranti perché è necessario unire quelle tabelle alla query per ottenere risultati significativi.

Ad esempio, supponiamo che tu abbia due entità: Indirizzo e Paese.

  • La relazione è: Indirizzo * ----- 1 Paese
  • L'entità Paese è fondamentalmente una chiave: coppia di valori (ad es. USA: Stati Uniti, CA: Canada, MX: Messico, ecc ...)
  • Per eseguire una query su questa struttura per tutti gli indirizzi negli Stati Uniti:

select * from Address where CountryCode = 'US'

  • Per eseguire la stessa query con chiavi surrogate:

select Address.* from Address join Country on Address.CountryID = Country.ID where Country.Code = 'US'

Mi sento a mio agio a imporre chiavi naturali per le tabelle di ricerca e chiavi surrogate per tutto il resto, se sono abbastanza sicuro che le chiavi naturali non cambieranno troppo spesso, se mai.


5

Dipende da come accedi ai dati. Se esegui molte ricerche di chiavi parziali (in cui selezioni i record in base ad esempio solo due delle tre chiavi), ti consigliamo di conservare le chiavi multiparte. OTOH, se hai molte relazioni 1: 1 con altre tabelle, probabilmente ha più senso avere una chiave surrogata.


1

Mi piace avere sempre una chiave primaria surrogata per ogni tabella. Ma non ci sono molte ragioni "difficili" per far valere ciò che ho sentito.

L'unica volta che ho mai avuto una chiave naturale multi-colonna mi ha morso è stato con ORM. Occasionalmente avrei problemi con una chiave primaria a più colonne usando Linq To Entities.


1

Non dire mai mai, ma unirsi su 4 colonne è un dolore. Più colonne hai con dati intelligenti, maggiori sono le possibilità che questi valori possano cambiare. I database possono essere configurati per mantenere l'integrità referenziale con aggiornamenti a cascata.

Puoi sempre creare un altro indice per gestire i valori univoci.

Le prestazioni sono probabilmente trascurabili nella maggior parte dei casi, ma è possibile testare le query con e senza la chiave surragate.


0

Trovo difficile trovare una buona ragione per imporre una chiave separata, ma come hai detto molte persone lo inseriscono.

Non trovo questo di aiuto (specialmente con l'archiviazione) quando si tratta di tabelle dei fatti / dettagli. L'esempio canonico una tabella dei fatti di vendita con (customer_key, store_key, product_key) con quantità non ha molto senso avere una chiave a livello di record.


0

Avere PK come autoincremento aumenta la seccatura se scopri che la tua chiave composita può effettivamente avere dei duplicati.


0

C'è una buona discussione che risale al 2002 su Ask Tom . È specifico per Oracle, ma la discussione più ampia è rilevante qualunque sia il database in uso.

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.