Czy każdy stół powinien mieć jeden zastępczy / sztuczny klucz podstawowy?

33

Rozumiem jedną zaletę kluczy zastępczych / sztucznych w ogóle - nie zmieniają się i może to być bardzo wygodne. Dotyczy to zarówno pojedynczego, jak i wielokrotnego pola - o ile są „sztuczne”.

Czasami jednak wydaje się, że zasadą jest posiadanie pola liczbowego z automatyczną inkrementacją jako klucza podstawowego każdej tabeli. Czy to zawsze najlepszy pomysł na taki klucz z jednym polem i dlaczego (lub dlaczego nie)?

Żeby było jasne, to pytanie nie dotyczy sztucznego, a naturalnego - lecz tego, czy wszystkie sztuczne klucze powinny być pojedynczego pola

Jack Douglas
źródło
1
patrz także dba.stackexchange.com/a/112632/1396
Jack Douglas

Odpowiedzi:

28

Powiem nie, nie zawsze, ale przez większość czasu tak. .

Oto niektóre okoliczności, w których nie potrzebujesz klucza zastępczego lub sztucznego:

  • Czyste tabele przecięć . Jeśli nie ma ryzyka, że ​​skrzyżowanie będzie celem klucza obcego i jeśli istnieje niewielkie lub żadne ryzyko, że skrzyżowanie przyciągnie niezależne atrybuty (tj. Coś innego niż FK do dwóch tabel nadrzędnych), można uniknąć użycia kombinacji FK jako PK z uczciwą pewnością.
  • Tabele przeglądowe ze statycznymi kluczami biznesowymi . Jeśli masz
    tabelę wyszukiwania z unikalnym kluczem biznesowym, który jest przymocowany zewnętrznie do Twojej
    firmy i który ma zerową szansę na zmianę w dowolnym
    praktycznym celu, to bezpośrednie użycie klucza biznesowego może
    uprościć sprawę . Przykładem może być lista
    kodów stanu lub prowincji lub lista standardowych numerów ANSI itp.
  • Tabele zawierające dane skonsolidowane z wielu niezależnych źródeł . Jeśli twój system ma wiele źródeł danych, które muszą zostać połączone w jedną tabelę, powiedzmy w centrali, czasem potrzebujesz klucza złożonego, który zawiera wartość klucza systemu źródłowego i kod wskazujący, jaki był system źródłowy.

Istnieją również sytuacje, w których stary wierny monotonicznie rosnący klucz zastępczy liczby całkowitej nie jest idealny. Możesz mieć klucze będące alfanumerycznymi odpowiednikami. Mogą to być:

  • Sytuacje, w których musisz scalić dane z wielu niezależnych źródeł. Aby uniknąć kolizji kluczy, możesz użyć identyfikatorów GUID zamiast kluczy TOŻSAMOŚCI.
  • Sytuacje, w których zmuszony jesteś używać nieliczbowych reprezentacji kluczy. Załóżmy, że masz bazę danych tablicy rejestracyjnej. Kluczem może być wartość alfanumeryczna zamiast czystej liczby.
  • Sytuacje, w których niektóre wymagania zewnętrzne wymuszają zastosowanie kompresji do wartości klucza. Zamiast używać 10 cyfr dla int32, możesz użyć sześciu podstawowych 36 cyfr.

Dlaczego przez większość czasu tak? Najbardziej podstawową odpowiedzią na to pytanie jest to, że jest to piekło, jeśli kiedykolwiek trzeba zmodyfikować wartość klucza podstawowego na dowolnym stole. Ponieważ prawie wszystko, co użytkownik może zobaczyć lub dotknąć, może w pewnym momencie podlegać aktualizacji, użycie widocznej wartości klucza zaprasza do czystego piekła. Użycie klucza zastępczego zapobiegnie wpadnięciu w tę pułapkę.

Powiedziawszy to, pamiętaj, że YAGNI ma możliwość zastosowania tej koncepcji. Nie musisz zmuszać tabel kodu z kluczami TOŻSAMOŚCI do każdego zakątka schematu, na wypadek, gdyby ktoś zdecydował, że symbol płci męskiej w tabeli pracowników musi zmienić się z M na X lub coś głupiego.

Joel Brown
źródło
„Użycie klucza zastępczego uchroni cię przed wpadnięciem w tę pułapkę”. Pytanie nie dotyczy zastępczego vs naturalnego, ale dotyczy zastępczych pojedynczego pola i wielu pól.
Jack Douglas,
Jak zauważyliście w komentarzu do własnej odpowiedzi, jesteśmy w stanie „zgodzić się nie zgodzić”, jeśli chodzi o to, co jest ostrożne w projektowaniu baz danych. Biorąc pod uwagę twoją edycję, nie dokonałbym rozróżnienia między kluczami zastępczymi a kluczami naturalnymi, więc mój drugi punkt jest spóźniony. Moje pozostałe punkty dotyczące tego, kiedy można odejść od klasycznego podejścia do tożsamości / sekwencji, nadal są aktualne.
Joel Brown,
Nie zmieniłem pytania, jak widać z historii, po prostu podkreśliłem, gdzie pomogło mi to w czytaniu przeglądarek
Jack Douglas
12

Nie.

Powiedziałbym, że z pewnością istnieją przypadki, gdy klucze pojedynczego pola są gorsze od kluczy złożonych, przynajmniej do celów kluczy obcych . Nie oznacza to, że nie powinieneś mieć klucza zastępczego dla pojedynczego pola, jeśli wolisz, ale ja osobiście wolę klucz, który jest najczęściej używany jako cel klucza obcego, aby był nazywany kluczem podstawowym

Spróbuję zilustrować mój punkt w następujących przykładach, w których:

  • brand to marka samochodów, np. Ford, Toyota itp
  • dealer to przedstawicielstwo fizyczne związane z marką (np. przedstawicielstwo Forda sprzedające tylko Forda)
  • model jest rodzajem samochodu, np. Ford Focus, Ford Fiesta itp
  • stock to bieżąca liczba samochodów na dziedzińcu dla każdego salonu

Jeśli utworzymy klucz zastępczy dla jednego pola dla dealeri modelw następujący sposób:

create table brand( brand_id integer primary key );

create table dealer( dealer_id integer primary key, 
                     brand_id integer references brand )

create table model( model_id integer primary key, 
                    brand_id integer references brand )

create table stock( model_id integer references model, 
                    dealer_id integer references dealer, 
                    quantity integer,
                      primary key(model_id, dealer_id) )

wtedy można wstawić wiersz stockłączący Forda dealerz modelem „Toyota”. Dodanie brand_id references branddo stocktylko sprawia, że problem gorzej. Z drugiej strony, jeśli zachowujemy klucz obcy jako część klucza podstawowego w następujący sposób:

create table brand( brand_id integer primary key );

create table dealer( brand_id integer references brand, 
                     dealer_id integer, 
                       primary key(brand_id, dealer_id) )

create table model( brand_id integer references brand, 
                    model_id integer, 
                      primary key(brand_id, model_id) )

create table stock( brand_id integer, 
                    model_id integer, 
                    dealer_id integer, 
                    quantity integer,
                      primary key(brand_id, model_id, dealer_id),
                      foreign key(brand_id, model_id) references model,
                      foreign key(brand_id, dealer_id) references dealer )

obecnie reguła, że ​​dealerzy „Ford” mogą przechowywać tylko samochody „Ford”, jest naturalnie egzekwowana przez model.

Należy zauważyć, że w przykładzie „klucze złożone” dealer_idmogą, ale nie muszą być unikalne, zgodnie z preferencjami. Nie musi być unikalny (tj. Klucz alternatywny), ale bardzo mało go gubi (być może trochę miejsca do przechowywania) i może być bardzo przydatny, tak zazwyczaj go konfiguruję, np .:

create table dealer( brand_id integer references brand, 
                     dealer_id serial unique, 
                       primary key(brand_id, dealer_id) )
Jack Douglas
źródło
3
Biorąc pod uwagę zwykłe zastrzeżenia dotyczące przykładów niekoniecznie perfekcyjnych pod każdym kątem, powiedziałbym, że ten typ projektu jest szczególnie kruchy. Jest coś satysfakcjonującego w znalezieniu sposobu wykorzystania DRI do egzekwowania reguł biznesowych, ale odbiera to również część twojej zdolności reagowania na zmiany. Jeśli Toyota kupi Forda, a nawet jeśli dealer Ford zdecyduje się sprzedać używaną Toyotę, reguły biznesowe kierowane przez DRI sprawią ci kłopot z konserwacją.
Joel Brown
1
Tak więc „reguły biznesowe mogą się zmienić”. Odnosi się to do każdej reguły biznesowej i zawsze będzie potencjalnie trudne do ponownego modelowania. Zazwyczaj słyszę, jakie są reguły biznesowe - nie decyduję o nich sam.
Jack Douglas,
1
Czy mówisz, że DRI nie powinno być w ogóle stosowane do egzekwowania reguł biznesowych? Czy to nie jedyne, co robi DRI? - nawet proste klucze obce są regułami biznesowymi egzekwowanymi przez DRI.
Jack Douglas,
4
Oczywiście DRI egzekwuje reguły biznesowe. Musisz zdecydować, które reguły będą egzekwowane w kodzie, a które w twoim schemacie. Zmiany schematu są prawie zawsze trudniejsze niż zmiany kodu. Istnieją dwa rodzaje reguł biznesowych, które można wprowadzić do modelu danych. Jeden należy tam, a drugi nie. Podstawowa natura danych, które są ważne dla Twojej firmy, niewiele się zmienia. Konkretne sposoby działania na tych danych są znacznie bardziej zmienne . W modelu danych należy zasada, że ​​samochody mają producenta. Reguła taka jak dealerzy nigdy nie sprzedaje dwóch marek samochodów.
Joel Brown,
4
„Zmiany schematu są prawie zawsze trudniejsze niż zmiany kodu” IMO jest przeciwieństwem. Właściwie nie zgadzam się z praktycznie wszystkim, co przed chwilą powiedziałeś, ale wątpię, by istniał jakiś argument z tobą, więc zostawię to przy tym.
Jack Douglas,
12

"to zależy"

Tak: Pola Identyfikator zastępczy / AUTONUMBER są dobre, gdy naturalny klucz jest szeroki i nienumeryczny. Uwaga: zakłada to połączenie „PK” i indeksu klastrowego, który występuje domyślnie w SQL Server i Sybase itp.

Nie: wiele / wiele tabel, gdy wystarczą 2 klucze nadrzędne. Lub gdy naturalny klucz jest krótki i ma ustaloną długość, np. Kod waluty

Oczywiście ORM braindead (czytaj: (n) Hibernacja) może przebijać te reguły ...

Edycja: ponowne czytanie pytania

Tabela wiele / wiele z 2 zastępczymi kluczami nadrzędnymi będzie miała wiele kolumn PK.
Jednak nie potrzebuje kolejnej kolumny zastępczej.

Jeśli tabela ma klucz zastępczy (TOŻSAMOŚĆ itp.), Nie musi to być wiele kolumn.

Możesz mieć superklucz obejmujący surogat, ale byłoby to wymuszanie innych reguł (np. Podtypów )

gbn
źródło