Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come creare una chiave primaria composita in SQL Server (esempio T-SQL)

Una chiave primaria composita è una chiave primaria composta da più colonne. Microsoft di solito si riferisce a queste chiavi primarie multicolonna nella sua documentazione.

Questo articolo fornisce un esempio di creazione di una chiave primaria composita usando Transact-SQL in SQL Server.

Puoi creare una chiave primaria composita proprio come faresti con una singola chiave primaria, tranne per il fatto che invece di specificare una sola colonna, fornisci il nome di due o più colonne, separate da una virgola.

In questo modo:

CONSTRAINT PK_Name PRIMARY KEY (Column1, Column2)

Esempio 1:creare una chiave primaria composita

Ecco un esempio di database che utilizza una chiave primaria composita.

Ai fini di questo esempio, creerò un database chiamato PK_Test :

CREATE DATABASE PK_Test;

Ora che il database è stato creato, andiamo avanti e creiamo le tabelle.

USE PK_Test;

CREATE TABLE Musician (
MusicianId int NOT NULL,
FirstName varchar(60),
LastName varchar(60),
CONSTRAINT PK_Musician PRIMARY KEY (MusicianID)
);

CREATE TABLE Band (
BandId int NOT NULL,
BandName varchar(255),
CONSTRAINT PK_Band PRIMARY KEY (BandId)
);

CREATE TABLE BandMember (
MusicianId int NOT NULL,
BandId int NOT NULL,
CONSTRAINT PK_BandMember PRIMARY KEY (MusicianID, BandId),
CONSTRAINT FK_BandMember_Band FOREIGN KEY (BandId) REFERENCES Band(BandId),
CONSTRAINT FK_BandMember_Musician FOREIGN KEY (MusicianId) REFERENCES Musician(MusicianId)
);

In questo esempio, il BandMember la tabella ha una chiave primaria multicolonna. In questo caso ogni colonna della chiave primaria è anche una chiave esterna alla chiave primaria di un'altra tabella, ma questo non è un requisito.

Il ragionamento alla base della progettazione del database di cui sopra è che un musicista potrebbe potenzialmente essere un membro di molte band. Inoltre, ogni band può avere molti musicisti. Quindi abbiamo una relazione molti-a-molti. Ecco perché il BandMember viene creata la tabella:viene utilizzata come tabella di riferimento incrociato tra il Musician tabella e la Band tavolo.

Questo caso particolare supporta una chiave primaria composita, perché un musicista che fa parte di una band dovrebbe essere un evento unico. In altre parole, non vorremmo più file con un musicista membro della stessa band. Ciò violerebbe l'integrità dei dati. Potrebbe anche causare scompiglio quando si tenta di mantenere l'integrità referenziale anche se si crea una relazione tra questa tabella e un'altra (cosa che facciamo qui).

Esempio 2 – Inserisci dati

Dopo aver appena eseguito il codice sopra, ora posso caricare il database con i dati:

INSERT INTO Musician
VALUES 
( 1, 'Ian', 'Paice' ),
( 2, 'Roger', 'Glover' ),
( 3, 'Richie', 'Blackmore' ),
( 4, 'Rod', 'Evans' ),
( 5, 'Ozzy', 'Osbourne' );

INSERT INTO Band
VALUES 
( 1, 'Deep Purple' ),
( 2, 'Rainbow' ),
( 3, 'Whitesnake' ),
( 4, 'Iron Maiden' );

INSERT INTO BandMember
VALUES 
( 1, 1 ),
( 1, 3 ),
( 2, 1 ),
( 2, 2 ),
( 3, 1 ),
( 3, 2 ),
( 4, 1 );

Esempio 3 – Query di base

Ora che i dati sono nel nostro database, eseguiamo una query per restituire alcuni di quei dati.

Ecco una query di base:

SELECT 
  CONCAT(m.FirstName, ' ', m.LastName) AS 'Musician',
  b.BandName AS 'Band'
FROM Musician m
JOIN BandMember bm
  ON m.MusicianId = bm.MusicianId
JOIN Band b 
  ON b.BandId = bm.BandId AND m.MusicianId = bm.MusicianId;

Risultato:

+------------------+-------------+
| Musician         | Band        |
|------------------+-------------|
| Ian Paice        | Deep Purple |
| Ian Paice        | Whitesnake  |
| Roger Glover     | Deep Purple |
| Roger Glover     | Rainbow     |
| Richie Blackmore | Deep Purple |
| Richie Blackmore | Rainbow     |
| Rod Evans        | Deep Purple |
+------------------+-------------+

Quindi, come previsto, questo restituisce solo i musicisti e le band che hanno una voce nel BandMember tabella di riferimento.

Esempio 4 – Query leggermente modificata

Ecco una versione modificata della query precedente che presenta i risultati in un modo diverso:

SELECT 
  b.BandName AS 'Band',
  STRING_AGG(CONCAT(m.FirstName, ' ', m.LastName), ', ') AS 'Musicians'
FROM Musician m
JOIN BandMember bm
  ON m.MusicianId = bm.MusicianId
JOIN Band b 
  ON b.BandId = bm.BandId AND m.MusicianId = bm.MusicianId
GROUP BY b.BandName;

Risultato:

+-------------+------------------------------------------------------+
| Band        | Musicians                                            |
|-------------+------------------------------------------------------|
| Deep Purple | Ian Paice, Roger Glover, Richie Blackmore, Rod Evans |
| Rainbow     | Roger Glover, Richie Blackmore                       |
| Whitesnake  | Ian Paice                                            |
+-------------+------------------------------------------------------+

Qui i risultati sono raggruppati per band e tutti i musicisti di ciascuna band vengono visualizzati come un elenco separato da virgole in un unico campo.

Per fare questo utilizzo il STRING_AGG() funzione di concatenare i musicisti.

Chiave esterna composita

Il problema con l'esempio sopra è che la maggior parte dei dati non è aggiornata. Alcuni di questi musicisti hanno effettivamente lasciato quelle band. E alcuni sono partiti e poi sono tornati in un secondo momento.

Come possiamo affrontarlo?

Potremmo creare un'altra tabella di riferimento per registrare il periodo di tempo in cui ogni musicista è membro di ogni band. Tale tabella dovrebbe fare riferimento a BandMember tabella tramite una chiave esterna. E poiché questa tabella ha una chiave primaria composita, dovremmo usare una chiave esterna composita sulla nuova tabella che fa riferimento ad essa.

Per un esempio, vedere Come creare una chiave esterna composita in SQL Server. Quell'articolo utilizza lo stesso esempio di cui sopra, tranne che con una tabella aggiuntiva con una chiave esterna composita che fa riferimento alla chiave primaria composita sopra.