Posso avere più chiavi primarie in una singola tabella?
Posso avere più chiavi primarie in una singola tabella?
Risposte:
Una tabella può avere una chiave primaria composita che è una chiave primaria composta da due o più colonne. Per esempio:
CREATE TABLE userdata (
userid INT,
userdataid INT,
info char(200),
primary key (userid, userdataid)
);
Aggiornamento: ecco un link con una descrizione più dettagliata delle chiavi primarie composite.
Una tabella può avere più chiavi candidate. Ogni chiave candidata è una colonna o un insieme di colonne che sono UNICHE, prese insieme e anche NON NULL. Pertanto, specificare i valori per tutte le colonne di qualsiasi chiave candidata è sufficiente per determinare che esiste una riga che soddisfa i criteri o nessuna riga.
Le chiavi candidate sono un concetto fondamentale nel modello di dati relazionali.
È pratica comune, se più chiavi sono presenti in una tabella, designare una delle chiavi candidate come chiave primaria. È inoltre pratica comune fare in modo che qualsiasi chiave esterna della tabella faccia riferimento alla chiave primaria, piuttosto che a qualsiasi altra chiave candidata.
Raccomando queste pratiche, ma non c'è nulla nel modello relazionale che richiede la selezione di una chiave primaria tra le chiavi candidate.
Questa è la risposta sia alla domanda principale che alla domanda di @ Kalmi
Quale sarebbe il punto di avere più colonne auto-generate?
Questo codice di seguito ha una chiave primaria composita. Una delle sue colonne è auto-incrementata. Funzionerà solo in MyISAM. InnoDB genererà un errore " ERRORE 1075 (42000): definizione della tabella errata; può esserci solo una colonna automatica e deve essere definita come chiave ".
DROP TABLE IF EXISTS `test`.`animals`;
CREATE TABLE `test`.`animals` (
`grp` char(30) NOT NULL,
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
`name` char(30) NOT NULL,
PRIMARY KEY (`grp`,`id`)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
Which returns:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
(Ho studiato molto questi)
Chiavi candidate : combinazione minima di colonne richiesta per identificare in modo univoco una riga della tabella.
Chiavi composte - 2 o più colonne.
Fonti:
https://en.wikipedia.org/wiki/Superkey
https://en.wikipedia.org/wiki/Candidate_key
https://en.wikipedia.org/wiki/Primary_key
https://en.wikipedia.org / wiki / Compound_key
Come notato dagli altri, è possibile avere chiavi primarie a più colonne. Va notato tuttavia che se si dispone di alcune dipendenze funzionali che non sono introdotte da una chiave, è necessario considerare la normalizzazione della relazione.
Esempio:
Person(id, name, email, street, zip_code, area)
Può esserci una dipendenza funzionale tra id -> name,email, street, zip_code and area
Ma spesso a zip_code
è associata a area
e quindi esiste una dipendenza funzionale interna tra zip_code -> area
.
Quindi si può considerare di dividerlo in un'altra tabella:
Person(id, name, email, street, zip_code)
Area(zip_code, name)
In modo che sia coerente con la terza forma normale .
La chiave primaria è una notazione molto sfortunata, a causa della connotazione di "primaria" e dell'associazione subconscia di conseguenza con il modello logico. Evito quindi di usarlo. Invece mi riferisco alla chiave surrogata del modello fisico e alle chiavi naturali del modello logico.
È importante che il Modello logico per ogni Entità abbia almeno una serie di "attributi aziendali" che comprendono una Chiave per l'entità. Boyce, Codd, Date et al. Si riferiscono a questi nel modello relazionale come chiavi candidate. Quando poi costruiamo tabelle per queste entità, le loro chiavi candidate diventano chiavi naturali in quelle tabelle. È solo tramite quelle chiavi naturali che gli utenti sono in grado di identificare in modo univoco le righe nelle tabelle; come chiavi surrogate dovrebbero essere sempre nascoste agli utenti. Questo perché Surrogate Keys non ha significato commerciale.
Tuttavia, il modello fisico per le nostre tabelle sarà in molti casi inefficiente senza una chiave surrogata. Ricorda che le colonne non coperte per un indice non cluster possono essere trovate (in generale) solo attraverso una Ricerca chiave nell'indice cluster (ignora le tabelle implementate come heap per un momento). Quando le nostre chiavi naturali disponibili sono ampie, questa (1) amplia la larghezza dei nostri nodi foglia non cluster, aumentando i requisiti di archiviazione e gli accessi in lettura per ricerche e scansioni di quell'indice non cluster; e (2) riduce il fan-out dal nostro indice cluster aumentando l'altezza e la dimensione dell'indice, aumentando ancora le letture e i requisiti di archiviazione per i nostri indici cluster; e (3) aumenta i requisiti di cache per i nostri indici cluster. inseguendo altri indici e dati dalla cache.
È qui che una piccola chiave surrogata, designata come RDBMS come "chiave primaria" si rivela vantaggiosa. Se impostato come chiave di clustering, in modo da essere utilizzato per le ricerche di chiavi nell'indice cluster da indici non cluster e ricerche di chiavi esterne da tabelle correlate, tutti questi svantaggi scompaiono. I nostri fan-out degli indici cluster aumentano di nuovo per ridurre l'altezza e le dimensioni dell'indice cluster, ridurre il carico di cache per i nostri indici cluster, ridurre le letture quando si accede ai dati attraverso qualsiasi meccanismo (scansione dell'indice, ricerca indice, ricerca chiavi non cluster o ricerca chiave esterna) e ridurre i requisiti di archiviazione per gli indici cluster e non cluster delle nostre tabelle.
Si noti che questi vantaggi si verificano solo quando la chiave surrogata è sia piccola sia la chiave di clustering. Se viene utilizzato un GUID come chiave di clustering, la situazione sarà spesso peggiore rispetto a quando fosse stata utilizzata la chiave naturale più piccola disponibile. Se la tabella è organizzata come un heap, il RowID a 8 byte (heap) verrà utilizzato per le ricerche di chiavi, che è migliore di un GUID a 16 byte ma meno performante di un numero intero a 4 byte.
Se un GUID deve essere utilizzato a causa di vincoli aziendali, vale la pena cercare una chiave di clustering migliore. Se, ad esempio, è possibile un identificatore di sito di piccole dimensioni e un "numero di sequenza di siti" a 4 byte, tale progetto potrebbe fornire prestazioni migliori rispetto a un GUID come chiave sostitutiva.
Se le conseguenze di un heap (forse hash join) fanno sì che lo spazio di archiviazione preferito sia necessario, i costi di una chiave di clustering più ampia devono essere bilanciati nell'analisi del trade-off.
Considera questo esempio ::
ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
dove la tupla " (P_Id, LastName) " richiede un vincolo di unicità e può essere un lungo LastName Unicode più un intero di 4 byte, sarebbe auspicabile (1) imporre dichiaratamente questo vincolo come " ADD CONSTRAINT pk_PersonID UNIQUE NONCLUSTERED (P_Id , LastName) "e (2) dichiarano separatamente una piccola chiave surrogata come" chiave primaria "di un indice cluster. Vale la pena notare che Anita probabilmente desidera solo aggiungere il LastName a questo vincolo per renderlo un campo coperto, che non è necessario in un indice cluster perché TUTTI i campi sono coperti da esso.
La capacità in SQL Server di designare una chiave primaria come non cluster è una sfortunata circostanza storica, a causa di una fusione del significato di "chiave naturale o candidata preferita" (dal modello logico) con il significato di "chiave di ricerca nella memoria" dal fisico Modello. La mia comprensione è che in origine SYBASE SQL Server utilizzava sempre un RowID a 4 byte, sia in un heap che in un indice cluster, come "chiave di ricerca in archivio" dal modello fisico.
Alcune persone usano il termine "chiave primaria" per indicare esattamente una colonna intera che ottiene i suoi valori generati da un meccanismo automatico. Ad esempio AUTO_INCREMENT
in MySQL o IDENTITY
in Microsoft SQL Server. Stai usando la chiave primaria in questo senso?
In tal caso, la risposta dipende dalla marca del database in uso. In MySQL, non puoi farlo, ricevi un errore:
mysql> create table foo (
id int primary key auto_increment,
id2 int auto_increment
);
ERROR 1075 (42000): Incorrect table definition;
there can be only one auto column and it must be defined as a key
In alcune altre marche di database, è possibile definire più di una colonna di generazione automatica in una tabella.
Non è possibile avere due chiavi primarie contemporaneamente. Ma (supponendo che non si sia incasinato il caso con una chiave composita), potrebbe essere necessario rendere unico un attributo.
CREATE t1(
c1 int NOT NULL,
c2 int NOT NULL UNIQUE,
...,
PRIMARY KEY (c1)
);
Tuttavia, notare che nel database relazionale una "super chiave" è un sottoinsieme di attributi che identificano in modo univoco una tupla o una riga in una tabella. Una "chiave" è una "super chiave" che ha una proprietà aggiuntiva che rimuove qualsiasi attributo dalla chiave, non la rende più una "super chiave" (o semplicemente una "chiave" è una super chiave minima). Se ci sono più chiavi, tutte sono chiavi candidate. Selezioniamo una delle chiavi candidate come chiave primaria. Ecco perché parlare di più chiavi primarie per una relazione o tabella è un conflitto.
Una chiave primaria è la chiave che identifica in modo univoco un record e viene utilizzata in tutti gli indici. Ecco perché non puoi averne più di uno. In genere è anche la chiave utilizzata per unire le tabelle figlio ma non è un requisito. Il vero scopo di un PK è assicurarsi che qualcosa ti consenta di identificare in modo univoco un record in modo che le modifiche ai dati influiscano sul record corretto e che possano essere creati gli indici.
Tuttavia, è possibile inserire più campi in una chiave primaria (un PK composito). Ciò renderà i tuoi join più lenti (soprattutto se si tratta di campi di tipo stringa più grandi) e i tuoi indici più grandi, ma potrebbe rimuovere la necessità di eseguire join in alcune tabelle figlio, quindi per quanto riguarda le prestazioni e il design, prendilo in considerazione base del caso. Quando lo fai, ogni campo in sé non è unico, ma la combinazione di essi lo è. Se anche uno o più campi in una chiave composita devono essere univoci, è necessario un indice univoco su di essa. È probabile però che se un campo è unico, questo è un candidato migliore per il PK.
Ora, a volte, hai più di un candidato per il PK. In questo caso scegline uno come PK o usi una chiave surrogata (preferisco personalmente chiavi surrogate per questa istanza). E (questo è fondamentale!) Aggiungi indici univoci a ciascuna delle chiavi candidate che non sono state scelte come PK. Se i dati devono essere univoci, hanno bisogno di un indice univoco indipendentemente dal fatto che sia il PK o meno. Questo è un problema di integrità dei dati. (Nota che questo vale anche ogni volta che usi una chiave surrogata; le persone si mettono nei guai con le chiavi surrogate perché dimenticano di creare indici univoci sulle chiavi candidate.)
Ci sono volte in cui vuoi più di una chiave surrogata (che di solito sono le PK se le hai). In questo caso quello che vuoi non è più PK, sono più campi con chiavi autogenerate. La maggior parte dei DB non lo consente, ma ci sono modi per aggirarlo. In primo luogo, considerare se il secondo campo potrebbe essere calcolato in base alla prima chiave generata automaticamente (Field1 * -1 per esempio) o forse la necessità di una seconda chiave generata automaticamente significa che è necessario creare una tabella correlata. Le tabelle correlate possono essere in una relazione uno a uno. Lo faresti aggiungendo il PK dalla tabella padre alla tabella figlio e quindi aggiungendo il nuovo campo generato automaticamente alla tabella e quindi tutti i campi appropriati per questa tabella. Quindi scegli una delle due chiavi come PK e metti un indice univoco sull'altra (il campo generato automaticamente non deve essere un PK). E assicurati di aggiungere l'FK al campo che si trova nella tabella padre. In generale, se non si dispone di campi aggiuntivi per la tabella figlio, è necessario esaminare il motivo per cui si ritiene di aver bisogno di due campi generati automaticamente.
Buone risposte tecniche sono state fornite in un modo migliore di quello che posso fare. Sono solo possibile aggiungere a questo argomento:
Se vuoi qualcosa che non è permesso / accettabile, è una buona ragione per fare un passo indietro.
Spero che possa aiutare qualcuno.
Sì, è possibile in SQL, ma non è possibile impostare più di una chiave primaria in MsAccess. Quindi, non conosco gli altri database.
CREATE TABLE CHAPTER (
BOOK_ISBN VARCHAR(50) NOT NULL,
IDX INT NOT NULL,
TITLE VARCHAR(100) NOT NULL,
NUM_OF_PAGES INT,
PRIMARY KEY (BOOK_ISBN, IDX)
);