Czy mogę mieć wiele kluczy podstawowych w jednej tabeli?
Czy mogę mieć wiele kluczy podstawowych w jednej tabeli?
Odpowiedzi:
Tabela może mieć złożony klucz podstawowy, który jest kluczem podstawowym złożonym z dwóch lub więcej kolumn. Na przykład:
CREATE TABLE userdata (
userid INT,
userdataid INT,
info char(200),
primary key (userid, userdataid)
);
Aktualizacja: Oto link z bardziej szczegółowym opisem złożonych kluczy podstawowych.
Tabela może mieć wiele kluczy kandydujących. Każdy klucz kandydujący jest kolumną lub zestawem kolumn, które są UNIKALNE, wzięte razem, a także NIE NULL. Zatem określenie wartości dla wszystkich kolumn dowolnego klucza kandydującego wystarczy, aby stwierdzić, że jest jeden wiersz spełniający kryteria lub w ogóle nie ma wierszy.
Klucze kandydujące są podstawową koncepcją w relacyjnym modelu danych.
Powszechną praktyką jest, jeśli w jednej tabeli znajduje się wiele kluczy, aby wyznaczyć jeden z kluczy kandydujących jako klucz podstawowy. Powszechną praktyką jest również powodowanie, że wszelkie klucze obce do tabeli odnoszą się do klucza podstawowego, a nie do dowolnego innego klucza kandydującego.
Polecam te praktyki, ale w modelu relacyjnym nie ma niczego, co wymagałoby wybrania klucza podstawowego spośród kluczy kandydujących.
To jest odpowiedź zarówno na główne pytanie, jak i na pytanie @ Kalmi
Jaki byłby sens posiadania wielu automatycznie generujących kolumn?
Poniższy kod ma złożony klucz podstawowy. Jedna z jej kolumn jest automatycznie zwiększana. Działa to tylko w MyISAM. InnoDB wygeneruje błąd „ BŁĄD 1075 (42000): Niepoprawna definicja tabeli; może istnieć tylko jedna kolumna automatyczna i należy ją zdefiniować jako klucz ”.
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 |
+--------+----+---------+
(Dużo ich studiowałem)
Klucze kandydujące - minimalna kombinacja kolumn wymagana do jednoznacznej identyfikacji wiersza tabeli.
Klucze złożone - 2 lub więcej kolumn.
Źródła:
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
Jak zauważyli inni, możliwe jest posiadanie kluczy głównych z wieloma kolumnami. Należy jednak zauważyć, że jeśli masz pewne zależności funkcjonalne , które nie są wprowadzane przez klucz, powinieneś rozważyć normalizację swojej relacji.
Przykład:
Person(id, name, email, street, zip_code, area)
Może istnieć zależność funkcjonalna między, id -> name,email, street, zip_code and area
ale często a zip_code
jest powiązana z a, area
a zatem istnieje wewnętrzna zależność funkcjonalna między zip_code -> area
.
Dlatego można rozważyć podzielenie go na inną tabelę:
Person(id, name, email, street, zip_code)
Area(zip_code, name)
Aby był zgodny z trzecią normalną formą .
Klucz podstawowy jest bardzo niefortunnym zapisem ze względu na konotację „Pierwotnego” i podświadomego skojarzenia z modelem logicznym. W ten sposób unikam jego używania. Zamiast tego mówię o kluczu zastępczym modelu fizycznego i kluczu naturalnego modelu logicznego.
Ważne jest, aby model logiczny dla każdej jednostki miał co najmniej jeden zestaw „atrybutów biznesowych”, które składają się na klucz dla encji. Boyce, Codd, Date i in. Określają je w modelu relacyjnym jako klucze kandydujące. Kiedy następnie budujemy tabele dla tych jednostek, ich klucze kandydujące stają się kluczami naturalnymi w tych tabelach. Tylko dzięki tym kluczom naturalnym użytkownicy mogą jednoznacznie identyfikować wiersze w tabelach; ponieważ klucze zastępcze powinny zawsze być ukryte przed użytkownikami. Wynika to z tego, że klucze zastępcze nie mają znaczenia biznesowego.
Jednak model fizyczny dla naszych tabel będzie w wielu przypadkach nieefektywny bez klucza zastępczego. Przypomnij sobie, że nieobjęte kolumny dla indeksu nieklastrowego można znaleźć (ogólnie) poprzez wyszukiwanie klucza w indeksie klastrowym (przez chwilę ignoruj tabele zaimplementowane jako stosy). Kiedy nasze dostępne Klucze Naturalne są szerokie, to (1) poszerza szerokość naszych nieklastrowych węzłów liści, zwiększając wymagania dotyczące przechowywania i dostęp do odczytu dla wyszukiwań i skanów tego nieklastrowanego indeksu; oraz (2) zmniejsza rozrzut z naszego indeksu klastrowego, zwiększając wysokość indeksu i jego rozmiar, ponownie zwiększając wymagania dotyczące odczytu i przechowywania naszych indeksów klastrowych; oraz (3) zwiększa wymagania pamięci podręcznej dla naszych indeksów klastrowych. wypędzanie innych indeksów i danych z pamięci podręcznej.
W tym przypadku korzystny jest mały klucz zastępczy, oznaczony jako RDBMS jako „klucz podstawowy”. Po ustawieniu jako klucz klastrowania, aby można go było używać do wyszukiwania kluczy w indeksie klastrowym z indeksów nieklastrowanych i wyszukiwania kluczy obcych z powiązanych tabel, wszystkie te wady znikają. Nasze rozkładania indeksów klastrowych ponownie zwiększają się, aby zmniejszyć wysokość i rozmiar indeksów klastrowych, zmniejszyć obciążenie pamięci podręcznej dla naszych indeksów klastrowanych, zmniejszyć odczyty podczas uzyskiwania dostępu do danych za pomocą dowolnego mechanizmu (czy to skanowania indeksu, wyszukiwania indeksu, wyszukiwania klucza nieklastrowanego lub klucza obcego) i zmniejsz wymagania dotyczące miejsca dla indeksów klastrowych i nieklastrowanych naszych tabel.
Należy zauważyć, że korzyści te występują tylko wtedy, gdy klucz zastępczy jest zarówno mały, jak i klucz klastrowania. Jeśli GUID jest używany jako klucz klastrowania, sytuacja często będzie gorsza niż w przypadku użycia najmniejszego dostępnego klucza naturalnego. Jeśli tabela jest zorganizowana jako sterta, wówczas 8-bajtowa (sterta) RowID będzie używana do wyszukiwania kluczy, co jest lepsze niż 16-bajtowy GUID, ale mniej wydajny niż 4-bajtowa liczba całkowita.
Jeśli z powodu ograniczeń biznesowych należy użyć identyfikatora GUID, warto poszukać lepszego klucza klastrowania. Jeśli na przykład wykonalny jest mały identyfikator witryny i 4-bajtowy „numer sekwencji witryny”, ten projekt może dać lepszą wydajność niż identyfikator GUID jako klucz zastępczy.
Jeśli konsekwencje stosu (być może złączenia mieszającego) powodują, że preferowane miejsce do magazynowania to koszty szerszego klucza klastrowania muszą zostać zrównoważone w analizie kompromisu.
Rozważ ten przykład:
ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
tam, gdzie krotka „ (P_Id, LastName) ” wymaga ograniczenia unikatowości i może być długim UnicName LastName i 4-bajtową liczbą całkowitą, pożądane byłoby (1) deklaratywne wymuszenie tego ograniczenia jako „ ADD CONSTRAINT pk_PersonID UNIQUE NONCLUSTERED (P_Id , LastName) ”i (2) oddzielnie deklarują mały klucz zastępczy jako„ klucz podstawowy ”indeksu klastrowego. Warto zauważyć, że Anita prawdopodobnie chce dodać LastName do tego ograniczenia, aby uczynić to pole objęte, co nie jest konieczne w indeksie klastrowym, ponieważ WSZYSTKIE pola są nim objęte.
Zdolność SQL Server do wyznaczenia klucza podstawowego jako nieklastrowanego jest niefortunną okolicznością historyczną, ze względu na połączenie znaczenia „preferowanego klucza naturalnego lub kandydującego” (z modelu logicznego) ze znaczeniem „klucz wyszukiwania w pamięci” z fizycznego Model. Rozumiem, że pierwotnie SYBASE SQL Server zawsze używał 4-bajtowego RowID, czy to w stercie, czy w indeksie klastrowym, jako „klucz wyszukiwania w magazynie” z modelu fizycznego.
Niektóre osoby używają terminu „klucz podstawowy”, aby oznaczać dokładnie kolumnę całkowitą, której wartości są generowane przez jakiś automatyczny mechanizm. Na przykład AUTO_INCREMENT
w MySQL lub IDENTITY
Microsoft SQL Server. Czy używasz klucza podstawowego w tym sensie?
Jeśli tak, odpowiedź zależy od marki używanej bazy danych. W MySQL nie możesz tego zrobić, pojawia się błąd:
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
W niektórych bazach danych innych marek możesz zdefiniować więcej niż jedną kolumnę automatycznego generowania w tabeli.
Posiadanie dwóch kluczy podstawowych jednocześnie nie jest możliwe. Ale (zakładając, że nie pomieszałeś sprawy z kluczem złożonym), może być potrzebne, aby uczynić jeden atrybut unikalnym.
CREATE t1(
c1 int NOT NULL,
c2 int NOT NULL UNIQUE,
...,
PRIMARY KEY (c1)
);
Należy jednak pamiętać, że w relacyjnej bazie danych „superklucz” to podzbiór atrybutów, które jednoznacznie identyfikują krotkę lub wiersz w tabeli. „Klucz” to „superklucz”, który ma dodatkową właściwość polegającą na usunięciu dowolnego atrybutu z klucza, dzięki czemu ten klucz nie jest już „superkluczem” (lub po prostu „klucz” to minimalny superklucz). Jeśli jest więcej kluczy, wszystkie są kluczami kandydującymi. Wybieramy jeden z kluczy kandydujących jako klucz podstawowy. Dlatego mówienie o wielu kluczach podstawowych dla jednej relacji lub tabeli jest konfliktem.
Klucz podstawowy to klucz, który jednoznacznie identyfikuje rekord i jest używany we wszystkich indeksach. Dlatego nie możesz mieć więcej niż jednego. Zasadniczo jest to również klucz używany podczas łączenia z tabelami podrzędnymi, ale nie jest to wymagane. Rzeczywistym celem PK jest upewnienie się, że coś pozwala jednoznacznie zidentyfikować rekord, aby zmiany danych wpłynęły na poprawny rekord i aby można było tworzyć indeksy.
Można jednak umieścić wiele pól w jednym kluczu podstawowym (złożonym PK). Spowoduje to spowolnienie połączeń (szczególnie jeśli są to większe pola typu łańcuchowego) i zwiększenie indeksów, ale może to wyeliminować potrzebę wykonywania połączeń w niektórych tabelach podrzędnych, jeśli chodzi o wydajność i projekt, weź to pod uwagę podstawa przypadku. Gdy to zrobisz, każde pole nie jest unikalne, ale ich kombinacja jest. Jeśli jedno lub więcej pól w kluczu złożonym również powinno być unikalne, potrzebujesz na nim unikalnego indeksu. Jest jednak prawdopodobne, że jeśli jedno pole jest unikalne, jest to lepszy kandydat na PK.
Czasami masz więcej niż jednego kandydata na PK. W takim przypadku wybierasz jeden jako PK lub używasz klucza zastępczego (osobiście wolę klucze zastępcze w tym przypadku). I (to jest krytyczne!) Dodajesz unikalne indeksy do każdego z kluczy kandydujących, które nie zostały wybrane jako PK. Jeśli dane muszą być unikalne, potrzebują unikalnego indeksu, niezależnie od tego, czy jest to PK, czy nie. Jest to problem z integralnością danych. (Uwaga: dotyczy to również każdego użycia klucza zastępczego; ludzie mają problemy z kluczami zastępczymi, ponieważ zapominają o tworzeniu unikalnych indeksów kluczy kandydujących).
Czasami potrzebujesz więcej niż jednego klucza zastępczego (którym są zwykle PK, jeśli je posiadasz). W tym przypadku nie chcesz więcej PK, to więcej pól z automatycznie generowanymi kluczami. Większość baz danych na to nie pozwala, ale istnieją sposoby na obejście tego. Najpierw zastanów się, czy drugie pole można obliczyć na podstawie pierwszego automatycznie wygenerowanego klucza (na przykład Field1 * -1), czy może potrzeba drugiego automatycznie wygenerowanego klucza naprawdę oznacza, że powinieneś utworzyć powiązaną tabelę. Powiązane tabele mogą być w relacji jeden do jednego. Wymusiłbyś to, dodając PK z tabeli nadrzędnej do tabeli podrzędnej, a następnie dodając nowe automatycznie wygenerowane pole do tabeli, a następnie wszystkie pola odpowiednie dla tej tabeli. Następnie wybierz jeden z dwóch kluczy jako PK i umieść na drugim unikatowy indeks (automatycznie wygenerowane pole nie musi być PK). I pamiętaj, aby dodać FK do pola, które znajduje się w tabeli nadrzędnej. Ogólnie rzecz biorąc, jeśli nie masz dodatkowych pól tabeli potomnej, musisz sprawdzić, dlaczego uważasz, że potrzebujesz dwóch automatycznie wygenerowanych pól.
Dobre odpowiedzi techniczne zostały podane w lepszy sposób niż ja. Mogę tylko dodać do tego tematu:
Jeśli chcesz czegoś, co jest niedozwolone / dopuszczalne, to dobry powód, aby cofnąć się.
Mam nadzieję, że to komuś pomoże.
Tak, jest to możliwe w SQL, ale nie możemy ustawić więcej niż jednego klucza podstawowego w MsAccess. Zatem nie wiem o innych bazach danych.
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)
);