Konwencja nazewnictwa klucza podstawowego / klucza obcego [zamknięta]

97

W naszej grupie deweloperów toczymy zaciekłą debatę dotyczącą konwencji nazewnictwa kluczy podstawowych i obcych. W naszej grupie są zasadniczo dwie szkoły myślenia:

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

lub

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

Wolę nie powielać nazwy tabeli w żadnej z kolumn (więc wolę opcję 1 powyżej). Koncepcyjnie jest to zgodne z wieloma zalecanymi praktykami w innych językach, w których nie używa się nazwy obiektu w nazwach jego właściwości. Myślę, że nazwanie klucza obcego EmployeeID(a Employee_IDmoże lepiej) mówi czytelnikowi, że jest to IDkolumna Employeetabeli.

Inni wolą opcję 2, w której nazwa klucza podstawowego jest poprzedzona nazwą tabeli, tak aby nazwa kolumny była taka sama w całej bazie danych. Rozumiem, ale teraz nie możesz wizualnie odróżnić klucza podstawowego od klucza obcego.

Myślę też, że nie ma sensu umieszczać nazwy tabeli w nazwie kolumny, ponieważ jeśli myślisz o tabeli jako o encji, a kolumna jako o właściwości lub atrybucie tej jednostki, myślisz o tym jako o atrybucie identyfikatora elementu Employee, a nie EmployeeIDatrybut pracownika. Nie chodzę ASK mojego współpracownika co jego PersonAgelub PersonGenderIS. Pytam go, jaki jest jego wiek.

Tak więc, jak powiedziałem, jest to zaciekła debata i ciągle o tym mówimy. Jestem zainteresowany, aby uzyskać nowe perspektywy.

Jeremy
źródło
1
pytanie powiela ten stackoverflow.com/questions/208580/…
Mike Henke Kwietnia
1
Przeczytałem więcej niż 10 podobnych pytań i ostatecznie znalazłem 3 najlepsze odpowiedzi tutaj są dobre: stackoverflow.com/a/465146/781695
użytkownik
Na marginesie: opcja 2 umożliwiłaby „naturalne połączenie”. Heck, dlaczego nadal nie zrobić tego w opcji 1, dodając „Employee.ID jako EmployeeID”. Ale lepszym sposobem na ćwiczenie wydaje się być „Dołącz” za pomocą „ON Employee.ID = Event.EmployeeID”.
Leo
W obu sytuacjach będziesz musiał użyć aliasu (lub „nazwa_tabeli.nazwa_kolumny”) w jednej lub więcej kolejek, ponieważ w obu przypadkach powtarzasz nazwy kolumn.
Please_Dont_Bully_Me_SO_Lords

Odpowiedzi:

52

To nie ma znaczenia. Nigdy nie spotkałem systemu, w którym istnieje prawdziwa różnica między wyborem 1 a wyborem 2.

Jeff Atwood miał jakiś świetny artykuł na ten temat. Zasadniczo ludzie dyskutują i dyskutują najbardziej wściekle na tematy, w których nie można im udowodnić, że się mylą. Albo z innego punktu widzenia, na te tematy, które można wygrać tylko dzięki argumentom ostatniego człowieka, opartym na wytrwałości w stylu obstrukcji.

Wybierz jeden i powiedz im, aby skupili się na problemach, które faktycznie mają wpływ na Twój kod.

EDYCJA: Jeśli chcesz się dobrze bawić, poproś ich, aby szczegółowo określili, dlaczego ich metoda jest lepsza w przypadku rekurencyjnych odwołań do tabel.

Russell Steen
źródło
28
+1, dla zdrowego rozsądku ... Są ważniejsze rzeczy, o które można się spierać ... Więc zrób to po swojemu (wybór 2)
Charles Bretana
5
A dla odwołującego się do siebie DRI, gdy istnieje więcej niż jeden FK, który odwołuje się do tego samego PK, MUSISZ naruszyć oba „standardy”, ponieważ dwie kolumny FK nie mogą mieć takiej samej nazwy ... np. z EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK itp. itd ...
Charles Bretana
76

Jeśli dwie kolumny mają tę samą nazwę w obu tabelach (konwencja nr 2), możesz użyć składni USING w SQL, aby zaoszczędzić trochę pisania i schematu:

SELECT name, address, amount
  FROM employees JOIN payroll USING (employee_id)

Kolejnym argumentem przemawiającym za konwencją nr 2 jest to, że w ten sposób zaprojektowano model relacyjny .

Znaczenie każdej kolumny jest częściowo przekazywane przez oznaczenie jej nazwą odpowiedniej domeny.

Steven Huwig
źródło
4
Składnia i semantyka SQL dają całkiem niezłą wskazówkę, jak należy go używać. np. składnia USING oznacza, że ​​kolumny z tą samą domeną powinny mieć tę samą nazwę, NULL = NULL -> NULL oznacza, że ​​NULL jest „nieznane”, a nie „nie dotyczy”, a ON UPDATE CASCADE oznacza, że ​​klucze muszą być tylko unikalne, a nie niezmienne.
Steven Huwig
6
Nawet lepiej, że pozwala to: SELECT name, address, amount FROM employees NATURAL JOIN payroll.
kiedy
5
Nie użyłbym naturalnego łączenia we wdrożonym kodzie, ponieważ jest bardziej kruche w przypadku dodawania schematu. Ale w przypadku interaktywnych zapytań jest świetny.
Steven Huwig
3
+1, ale zawsze jest wyjątek. Na przykład, jeśli masz dwie kolumny w liście płac, które są obydwoma kluczami obcymi dla pracownika (na przykład jedno odniesienie do osoby, której wypłacane jest wynagrodzenie, a drugie do menedżera z uprawnieniami budżetowymi). Ale nie możemy nazwać obu kluczy obcych employee_id.
Bill Karwin
1
Słowo kluczowe „using” jest specyficzne dla MySql. Nie działa w T-SQL - niestety.
birdus
12

Myślę, że to zależy od tego, w jaki sposób złożysz wniosek. Jeśli używasz ORM lub projektujesz swoje tabele do reprezentowania obiektów, opcja 1 może być dla Ciebie.

Lubię kodować bazę danych jako własną warstwę. Kontroluję wszystko, a aplikacja po prostu wywołuje procedury składowane. Dobrze jest mieć zestawy wyników z pełnymi nazwami kolumn, zwłaszcza gdy jest wiele połączonych tabel i zwróconych wiele kolumn. W przypadku tego rodzaju aplikacji podoba mi się opcja 2. Bardzo lubię, gdy nazwy kolumn pasują do złączeń. Pracowałem na starych systemach, w których nie pasowały i był to koszmar,

KM.
źródło
4
+1 za konieczność znalezienia złączeń z niepasującymi nazwami kolumn
Raj More
4
w "starych systemach" handicap nazw o długości 8 znaków, który boli o wiele bardziej. Jestem skłonny postawić się na skraju i spekulować, że posiadanie PK o nazwie ID nie było główną przyczyną koszmaru w starych systemach, z którymi miałeś do czynienia. Również „zasysane przez stare systemy” jest często używane w tworzeniu oprogramowania, zwłaszcza baz danych. Rutynowo widzę ludzi uzasadniających każdą praktykę A, opierając się na tym, jak działała ona w ich doświadczeniach z systemem DB wydanym ponad 10 lat temu.
Russell Steen
2
dzisiejszy stan techniki aplikacji będzie stare gówno w ciągu kilku lat. możesz nawet przepisać interfejs lub użyć danych na innej platformie, ale Twoje dane (w tym nazwy kolumn) będą musiały przetrwać próbę czasu.
KM.
2
Więc ludzie 20 lat temu powinni byli w jakiś sposób używać nazw kolumn, które mają dziś sens, mimo że miały tylko 8 znaków? Formaty przechowywania danych zmieniły się drastycznie w ciągu ostatnich 20 lat i zmienią się ponownie w ciągu następnych 20. Nie ma sposobu, aby wykazać, że Twoje preferencje przetrwają próbę czasu lepiej niż inne wymienione metody. „Nazwy kolumn” same w sobie mogą być „starymi bzdurami” do czasu, gdy ludzie będą toczyć tę dyskusję za 20 lat, ponieważ nasza zdolność do przechowywania i manipulowania danymi wzrasta. Tabele to ludzka konstrukcja, która niedoskonale reprezentuje relacje danych ...
Russell Steen
1
Dziękuję za dobrze uzasadnioną odpowiedź intelektualną.
Russell Steen
3

Żadna konwencja nie działa we wszystkich przypadkach, więc po co w ogóle ją mieć? Użyj rozumu...

np. w przypadku tabeli odwołującej się do siebie, gdy istnieje więcej niż jedna kolumna FK, która odwołuje się do PK tej samej tabeli, MUSISZ naruszyć oba "standardy", ponieważ dwie kolumny FK nie mogą być nazwane tak samo ... np. , EmployeeTable z EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, ...

Charles Bretana
źródło
1
+1 za rzeczywistą odpowiedź techniczną
DVK
Dobra, odpowiednia odpowiedź, ale argumenty zawarte w odpowiedzi Demsa mija się z celem.
JYelton
3

Zgadzam się, że nie ma między nimi wyboru. Dla mnie o wiele ważniejszą rzeczą w przypadku obu standardów jest część „standardowa”.

Jeśli ludzie zaczną „robić swoje”, powinni zostać związani przez swoich netherów. MOIM ZDANIEM :)

MatBailie
źródło
3
+1 za uznanie, że konsekwencja jest ważniejsza niż bycie „właściwym” (w tym przypadku)
Russell Steen
-1 za próbę zastosowania „głupiej spójności”. Stare chińskie przysłowie mówi: „Głupia konsekwencja to hobgoblin dla prostych umysłów”.
Charles Bretana
@charles: w świecie, w którym różni ludzie utrzymują wzajemnie kod, często gdy autor odszedł, a dokumentacja jest przestarzała lub nie istnieje, nie jest to głupia spójność. Tak się cieszę, że nie pracuję z Tobą ...
MatBailie
@Dems, bez zamierzonej obrazy, ale jest to głupie z dwóch powodów. 1) Istnieją powszechne, jasno zrozumiałe scenariusze, w których JAKIEKOLWIEK standard musiałby zostać naruszony. (zobacz moją odpowiedź na przykłady i 2), ponieważ przynajmniej w tej kwestii norma dodałaby bardzo mało wartości, z wyjątkiem tego, że ludzie, którzy lubią standardy, czują się bardziej komfortowo ...
Charles Bretana
1
można by się spierać, że „ID” jest bardziej spójne - bo jak tylko wprowadzisz język angielski „carID” w tabeli „samochody” lub „samochód”? „sheepID” w tabeli „owce” lub „owce” - rzeczy zaczynają być niekonsekwentne. Jeśli trzymasz się "ID" i pojedynczych nazw tabel - jest to nie tylko spójne, ale również gra ładnie z wieloma ORMami / wymaga mniej konfiguracji (np. Dapper Contrib)
niico
3

Czy rozważałeś następujące kwestie?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee
Wouter
źródło
3
Nie mogę znieść, kiedy ludzie odrzucają głos i nie podają powodu. To jest całkowicie poprawna odpowiedź, czy jest ona przyjemna dla niektórych, czy nie, to inne pytanie, ale jest to subiektywne i nie wymaga głosowania przeciw.
Jeremy
1
Dziękuję za zwrócenie uwagi. Byłbym również zainteresowany powodami, dla których nie używałbyś tego formatu. I jestem pewien, że będą dobre powody ...
Wouter
Jest to najlepsze wyjście, ponieważ nie będziesz musiał używać table_name.column_namew zapytaniach i nie będziesz musiał używać aliasu dla nazw kolumn, jeśli nie masz powtarzających się nazw ...
Please_Dont_Bully_Me_SO_Lords
1
Można to uznać za formę notacji węgierskiej. Rozważ więc argumenty za i przeciw.
Fred
2

Konwencja, której używamy w pracy, jest bardzo zbliżona do A, z wyjątkiem tego, że nazywamy tabele w liczbie mnogiej (tj. „Pracownicy”) i używamy podkreślenia między tabelą a nazwą kolumny. Zaletą tego jest to, że aby odwołać się do kolumny, należy podać albo „identyfikator_pracowników”, albo „id.pracowników”, w zależności od tego, jak chcesz uzyskać do niej dostęp. Jeśli musisz określić, z której tabeli pochodzi kolumna, „ID pracowników.pracowników” jest zdecydowanie zbędne.

Jarett Millard
źródło
Nie zdecydowałem, czy lubię nazwy tabel w liczbie mnogiej. Używając liczby pojedynczej, zapytania wydają się być bardziej czytelne („pracownik.nazwa” w przeciwieństwie do „pracowników.nazwa”). Wydaje się, że nawet przy złączeniach lepiej czyta się, gdy łączysz pojedyncze rekordy z inną tabelą. Jednak nazwy tabel w liczbie mnogiej wydają się dokładniejsze, gdy myślimy o tabeli, a nie zapytaniu. Będę trzymał się liczby pojedynczej, ponieważ tego używamy, ale myślę, że jest to również właściwa droga (chociaż znowu wielu się nie zgadza)
MatBailie
Tak. Sądzę, że to bardziej osobiste preferencje i / lub cokolwiek, do czego przywykłeś.
Jarett Millard
2

Jeśli patrzysz na kod aplikacji, a nie tylko zapytania do bazy danych, niektóre rzeczy wydają mi się jasne:

  1. Definicje tabel zwykle odwzorowują bezpośrednio klasę opisującą jeden obiekt, więc powinny być pojedyncze. Aby opisać zbiór obiektu, zwykle dodaję „Array”, „List” lub „Collection” do nazwy w liczbie pojedynczej, ponieważ to wyraźniej niż użycie liczby mnogiej wskazuje nie tylko, że jest to zbiór, ale także jakiego rodzaju jest to zbiór to jest. W tym widoku widzę nazwę tabeli nie jako nazwę kolekcji, ale nazwę typu obiektu, którego jest ona zbiorem. Administrator DBA, który nie pisze kodu aplikacji, może przeoczyć ten punkt.

  2. Dane, z którymi mam do czynienia, często używają „ID” do celów identyfikacji innych niż kluczowe. Aby wyeliminować pomyłki między kluczami „ID” i „identyfikatorami” niebędącymi kluczami, jako nazwy klucza podstawowego używamy „Klucz” (tak właśnie jest, prawda?) Poprzedzony nazwą tabeli lub skrótem nazwa tabeli. To prefiksowanie (i zastrzegam to tylko dla klucza podstawowego) sprawia, że ​​nazwa klucza jest unikalna, co jest szczególnie ważne, ponieważ używamy nazw zmiennych, które są takie same jak nazwy kolumn bazy danych, a większość klas ma rodzica, identyfikowanego przez nazwę klucz nadrzędny. Jest to również konieczne, aby upewnić się, że nie jest to zastrzeżone słowo kluczowe, którym jest sam „Klucz”. Aby ułatwić zachowanie spójności nazw kluczowych zmiennych i zapewnić programy, które wykonują łączenia naturalne, Klucze obce mają taką samą nazwę, jaka jest używana w tabeli, w której są kluczem podstawowym. Nieraz spotkałem się z programami, które działają znacznie lepiej w ten sposób, używając łączeń naturalnych. W tej ostatniej kwestii przyznaję się do problemu z tabelami odwołującymi się do samych siebie, z których korzystałem. W tym przypadku zrobiłbym wyjątek od reguły nazewnictwa kluczy obcych. Na przykład użyłbym ManagerKey jako klucza obcego w tabeli Employee, aby wskazać inny rekord w tej tabeli.

Bruce Patin
źródło
Wiele obiektowo-relacyjnych maperów (ORM), takich jak Entity Framework, umożliwia mapowanie tabeli do klasy o innej nazwie. Dzięki temu możesz mieć klasę o nazwie „Użytkownik” i tabelę o nazwie „Użytkownicy”.
Fred
2

Podoba mi się konwencja nr 2 - badając ten temat i znajdując to pytanie przed wysłaniem własnego, natknąłem się na problem, w którym:

Wybieram * z tabeli z dużą liczbą kolumn i łączę ją z drugą tabelą, która podobnie ma dużą liczbę kolumn. Obie tabele mają kolumnę „id” jako klucz podstawowy, co oznacza, że ​​muszę specjalnie wybrać każdą kolumnę (o ile wiem), aby te dwie wartości były unikalne w wyniku, tj .:

SELECT table1.id AS parent_id, table2.id AS child_id

Chociaż użycie konwencji nr 2 oznacza, że ​​nadal będę mieć w wyniku kilka kolumn o tej samej nazwie, mogę teraz określić, którego identyfikatora potrzebuję (rodzic lub dziecko) i, jak zasugerował Steven Huwig, USINGstwierdzenie to jeszcze bardziej upraszcza sprawę .

JYelton
źródło
2
SELECT *w każdym razie nie dotyczy (większości) zapytań produkcyjnych, więc nie jest to zbyt duży powód, aby wybierać standard nazewnictwa.
P Daddy
1
Nie zgadzam się: czy mógłbyś podać link do powodu, dla którego tak jest? Nie podoba mi się pomysł utrzymywania nazw 80 kolumn w moim zapytaniu.
JYelton
W tej chwili nie można znaleźć linku (trudne do wyszukania w wyszukiwarce „*”), ale opiszę podstawowe punkty: (1) zmiany w tabelach mogą negatywnie wpłynąć na Twoją aplikację, (2) może to być źle wpływa na wydajność i (3) jawne określenie, jakich danych faktycznie potrzebujesz, może ułatwić zrozumienie kodu. Te punkty mogą się rozszerzyć i są wyjątki (jak wspomniałem), ale nie jest to właściwe w tym miejscu. Jeśli opublikujesz to jako nowe pytanie, ja (i inni) chętnie omówię to dalej.
P Daddy
2
Mogę to zrobić. Zdaję sobie sprawę z korzyści wynikających z wydajności, ale muszę wziąć pod uwagę czas poświęcony na edycję kodu. Zawsze szukam sposobów na poprawę interakcji między aplikacją a bazą danych. Dzięki.
JYelton
1
Nie jestem pewien, czy odpowiedź SELECT *brzmi „nie” w przypadku większości zapytań produkcyjnych. Jeśli znacznie przyspieszy to rozwój i sprawi, że Twój kod będzie bardziej zwięzły i czytelny - co pozwoli Ci skupić się na ważniejszych sprawach - dlaczego nie SELECT *? Zależy to w dużej mierze od okoliczności każdej sytuacji i jest kompromisem między wieloma czynnikami. Jedna zasada rzadko pasuje do wszystkiego.
niico
2

Zawsze używałem userId jako PK na jednej tabeli i userId na innej tabeli jako FK. Poważnie myślę o używaniu userIdPK i userIdFK jako nazw identyfikujących je od siebie. Pomoże mi to szybko zidentyfikować PK i FK podczas patrzenia na tabele i wygląda na to, że wyczyści kod podczas używania PHP / SQL do dostępu do danych, ułatwiając zrozumienie. Zwłaszcza, gdy ktoś inny patrzy na mój kod.

Ross
źródło
1

Używam konwencji nr 2. Pracuję teraz ze starszym modelem danych, w którym nie wiem, co oznacza w danej tabeli. Jaka szkoda bycia gadatliwym?

Kucyki OMG
źródło
1

Co powiesz na nazwanie klucza obcego

role_id

gdzie rola jest rolą, którą odwołuje się podmiot do danej tabeli. Rozwiązuje to problem rekursywnych odwołań i wielu fks do tej samej tabeli.

W wielu przypadkach będzie identyczna z nazwą tabeli, do której się odwołuje. W takim przypadku staje się identyczny z jedną z twoich propozycji.

W każdym razie długie kłótnie to zły pomysł

Jens Schauder
źródło
0

"Gdzie w" zamówieniu WEWNĘTRZNY DOŁĄCZ pracownika NA order.employee_id = worker.id "czy jest potrzeba dodatkowych kwalifikacji?".

Dodatkowe kwalifikacje nie są potrzebne, ponieważ kwalifikacje, o których mówiłem, już istnieją.

„powodem, dla którego użytkownik biznesowy odwołuje się do identyfikatora zamówienia lub identyfikatora pracownika, jest zapewnienie kontekstu, ale na poziomie bazy danych masz już kontekst, ponieważ odwołujesz się do tabeli”.

Módlcie się, powiedzcie mi, jeśli kolumna nosi nazwę „ID”, to jak dokładnie można to zrobić „odwoływanie się [sic] do tabeli”, chyba że poprzez zakwalifikowanie tego odniesienia do kolumny ID dokładnie w sposób, o którym mówiłem?


źródło