złożony klucz podstawowy to klucz podstawowy składający się z wielu kolumn. Microsoft zwykle określa je jako wielokolumnowe klucze podstawowe w swojej dokumentacji.
W tym artykule przedstawiono przykład tworzenia złożonego klucza podstawowego przy użyciu języka Transact-SQL w programie SQL Server.
Złożony klucz podstawowy można utworzyć tak, jak tworzy się pojedynczy klucz podstawowy, z tą różnicą, że zamiast określać tylko jedną kolumnę, należy podać nazwę dwóch lub więcej kolumn oddzielonych przecinkiem.
Tak:
CONSTRAINT PK_Name PRIMARY KEY (Column1, Column2)
Przykład 1 – Utwórz złożony klucz podstawowy
Oto przykład bazy danych wykorzystującej złożony klucz podstawowy.
Na potrzeby tego przykładu stworzę bazę danych o nazwie PK_Test :
CREATE DATABASE PK_Test;
Teraz, gdy baza danych została utworzona, przejdźmy dalej i utwórzmy tabele.
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) );
W tym przykładzie BandMember
tabela ma wielokolumnowy klucz podstawowy. W tym przypadku każda kolumna w kluczu podstawowym jest również kluczem obcym do klucza podstawowego innej tabeli, ale nie jest to wymagane.
Uzasadnieniem powyższego projektu bazy danych jest to, że muzyk może potencjalnie być członkiem wielu zespołów. Ponadto każdy zespół może mieć wielu muzyków. Mamy więc relację „wielu do wielu”. Dlatego BandMember
tworzona jest tabela – jest używana jako tabela odniesień między Musician
tabela i Band
stół.
Ten szczególny przypadek obsługuje złożony klucz podstawowy, ponieważ muzyk będący członkiem zespołu powinien być wyjątkowym wydarzeniem. Innymi słowy, nie chcielibyśmy wielu rzędów z muzykiem będącym członkiem tego samego zespołu. To naruszyłoby integralność danych. Może to również spowodować spustoszenie, gdy próbujemy zachować integralność referencyjną, nawet jeśli kiedykolwiek stworzymy relację między tą tabelą a inną (co robimy tutaj).
Przykład 2 – Wstaw dane
Po uruchomieniu powyższego kodu mogę teraz załadować bazę danych danymi:
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 );
Przykład 3 – Podstawowe zapytanie
Teraz, gdy dane znajdują się w naszej bazie danych, uruchom zapytanie, aby zwrócić niektóre z tych danych.
Oto podstawowe zapytanie:
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;
Wynik:
+------------------+-------------+ | 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 | +------------------+-------------+
Tak więc, zgodnie z oczekiwaniami, zwracane są tylko ci muzycy i zespoły, które mają wpis w BandMember
tabela referencyjna.
Przykład 4 – Nieco zmodyfikowane zapytanie
Oto zmodyfikowana wersja powyższego zapytania, która prezentuje wyniki w inny sposób:
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;
Wynik:
+-------------+------------------------------------------------------+ | Band | Musicians | |-------------+------------------------------------------------------| | Deep Purple | Ian Paice, Roger Glover, Richie Blackmore, Rod Evans | | Rainbow | Roger Glover, Richie Blackmore | | Whitesnake | Ian Paice | +-------------+------------------------------------------------------+
Tutaj wyniki są pogrupowane według zespołów, a wszyscy muzycy z każdego zespołu są wyświetlani jako lista oddzielona przecinkami w jednym polu.
Aby to zrobić, używam STRING_AGG()
funkcja łączenia muzyków.
Złożony klucz obcy
Problem z powyższym przykładem polega na tym, że większość danych jest nieaktualna. Niektórzy z tych muzyków faktycznie opuścili te zespoły. A niektórzy wyjechali, a potem wrócili w późniejszym terminie.
Jak sobie z tym poradzić?
Moglibyśmy stworzyć kolejną tabelę referencyjną, aby zarejestrować okres, w którym każdy muzyk jest członkiem każdego zespołu. Taka tabela musiałaby odwoływać się do BandMember
tabeli za pomocą klucza obcego. A ponieważ ta tabela ma złożony klucz podstawowy, musielibyśmy użyć złożonego klucza obcego w nowej tabeli, która się do niej odwołuje.
Zobacz, jak utworzyć złożony klucz obcy w programie SQL Server, aby zapoznać się z przykładem. W tym artykule wykorzystano ten sam przykład co powyżej, z wyjątkiem dodatkowej tabeli ze złożonym kluczem obcym, który odwołuje się do powyższego złożonego klucza podstawowego.