Mój nauczyciel t-sql powiedział nam, że nazywanie naszej kolumny PK „Id” jest uważane za złą praktykę bez dalszych wyjaśnień.
Dlaczego nazywanie tabeli PK kolumny „Id” jest uważane za złą praktykę?
Mój nauczyciel t-sql powiedział nam, że nazywanie naszej kolumny PK „Id” jest uważane za złą praktykę bez dalszych wyjaśnień.
Dlaczego nazywanie tabeli PK kolumny „Id” jest uważane za złą praktykę?
Odpowiedzi:
Mam zamiar wyjść i powiedzieć: to nie jest naprawdę zła praktyka (a nawet jeśli tak, to wcale nie jest taka zła).
Można argumentować (jak zauważył Chad ), że może maskować błędy, jak w poniższym zapytaniu:
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.Id = car.ManufacturerId
JOIN models mod
ON mod.Id = car.ModelId
JOIN colors col
ON mfg.Id = car.ColorId
ale można to łatwo złagodzić, nie używając małych aliasów dla nazw tabel:
SELECT *
FROM cars
JOIN manufacturer
ON manufacturer.Id = cars.ManufacturerId
JOIN models
ON models.Id = cars.ModelId
JOIN colors
ON manufacturer.Id = cars.ColorId
Praktyka ZAWSZE przy użyciu trzyliterowych skrótów wydaje mi się o wiele gorsza niż używanie nazwy kolumny id
. (Przypadek: kto właściwie skróciłby nazwę tabeli cars
skrótem car
? Jakiemu celowi to służy?)
Chodzi o to: bądź konsekwentny. Jeśli Twoja firma używa Id i często popełniasz powyższy błąd, nabądź zwyczaju używania pełnych nazw tabel. Jeśli Twoja firma zbanuje kolumnę Id, pospiesz się i zastosuj dowolną konwencję nazewnictwa.
Skoncentruj się na uczeniu się rzeczy, które W rzeczywistości są złymi praktykami (takimi jak wiele zagnieżdżonych skorelowanych zapytań cząstkowych), zamiast zastanawiać się nad takimi problemami. Problem nazwania kolumn „ID” jest bliższy kwestii gustu niż złej praktyce.
UWAGA DLA REDAKTORÓW: Błąd w tym zapytaniu jest celowy i służy do podkreślenia. Proszę przeczytać pełną odpowiedź przed edycją.
cars
-> car
. Dzięki Bogu - uratowałeś mi palce). Nie czytaj zbyt głęboko w to.
cars
i manufacturer
. Jeden jest w liczbie mnogiej, a drugi nie. Jeśli ludzie chcą wybierać w db, jest to zła praktyka, którą należy wybrać.
Ponieważ gdy masz tabelę z kluczem obcym, nie możesz nazwać tego klucza obcego „Id”. Masz nazwę tabeli to TableId
I wtedy wygląda twoje dołączenie
SELECT * FROM cars c JOIN manufacturer m ON m.Id = c.ManufacturerId
I idealnie, twój stan powinien mieć taką samą nazwę pola po obu stronach
SELECT * FROM cars c JOIN manufacturer m ON m.ManufacturerId = c.ManufacturerId
Więc choć wydaje się zbędne nazywanie Id jako ManufacturerId, zmniejsza prawdopodobieństwo wystąpienia błędów w twoich warunkach łączenia, gdy błędy stają się oczywiste.
Wydaje się to proste, ale kiedy dołączysz do kilku stolików, bardziej prawdopodobne jest, że popełnisz błąd, znajdź ten poniżej ...
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.Id = car.ManufacturerId
JOIN models mod
ON mod.Id = car.ModelId
JOIN colors col
ON mfg.Id = car.ColorId
Podczas prawidłowego nazewnictwa błąd wystaje ...
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.ManufacturerId = car.ManufacturerId
JOIN models mod
ON mod.ModelId = car.ModelId
JOIN colors col
ON mfg.ManufacturerId = car.ColorId
Innym powodem nazwania ich Id jest „zły” jest to, że kiedy pytasz o informacje z kilku tabel, musisz zmienić nazwę kolumn Id, abyś mógł je rozróżnić.
SELECT manufacturer.Id as 'ManufacturerId'
,cars.Id as 'CarId'
--etc
FROM cars
JOIN manufacturer
ON manufacturer.Id = cars.Id
Przy dokładnych nazwach jest to mniejszy problem
SELECT * FROM cars c JOIN manufacturer m ON manufacturer.Id = c.ManufacturerId
. Używałem id
od lat i nigdy nie znalazłem, co opisałeś, prawdziwego problemu.
SELECT manufacturer.id FROM ...
. Każda wynikająca z tego trudność id
może być pokonana bardzo łatwo, dzięki czemu jest to po prostu kwestia gustu.
Biblioteka ActiveRecord Ruby i GORM Groovy'ego domyślnie używają „id” dla klucza zastępczego. Podoba mi się ta praktyka. Powielanie nazwy tabeli w nazwie każdej kolumny jest zbędne, żmudne w pisaniu i bardziej żmudne w czytaniu.
Wspólne lub kluczowe nazwy kolumn, takie jak „Nazwa” lub „Id”, powinny być poprzedzone nazwą tabeli.
Usuwa niejednoznaczność, jest łatwiejszy do wyszukiwania, oznacza o wiele mniej aliasów kolumn, gdy potrzebne są obie wartości „Id”.
Rzadziej używana kolumna kontroli lub inna niż klucz (powiedzmy LastUpdatedDateTime) nie ma znaczenia
name
i id
? Dlaczego każda kolumna nie ma prefiksu z nazwą tabeli? Wydaje się, że wybranie tych dwóch nazw w celu wprowadzenia prefiksu wydaje się arbitralne. Koncepcyjnie, musisz mieć tabelę, aby mimo to mieć kontekst kolumny. Dlaczego nie użyć tej nazwy tabeli do wyjaśnienia zapytania: Person.Name, Animal.Name, Part.Name, ...
Ten wątek jest martwy, ale chciałbym dodać, że IMO nie stosując Id
jest złą praktyką. Id
Kolumna specjalnym; jest to klucz podstawowy. Każda tabela może mieć dowolną liczbę kluczy obcych, ale może mieć tylko jeden klucz, który jest podstawowy. W bazie danych, w której są wywoływane wszystkie klucze podstawowe Id
, jak tylko spojrzysz na tabelę, wiesz dokładnie, która kolumna jest kluczem podstawowym.
Uwierz mi, od miesięcy spędzam cały dzień codziennie pracując w wielu dużych bazach danych (Salesforce), a najlepsze, co mogę powiedzieć o schematach, to to, że każda tabela ma podstawowy klucz o nazwie Id
. Zapewniam cię, że nigdy nie mylę się przy łączeniu klucza podstawowego z kluczem obcym, ponieważ wywoływana jest PK Id
. Inną rzeczą, o której ludzie nie wspominali, jest to, że tabele mogą mieć długie głupie nazwy, takie jak Table_ThatDoesGood_stuff__c
; ta nazwa jest wystarczająco zła, ponieważ architekt miał kaca rano, gdy wymyślił tę tabelę, ale teraz mówisz mi, że złą praktyką jest nie wywoływanie klucza podstawowego Table_ThatDoesGood_stuff__cId
(pamiętając, że nazwy kolumn SQL nie rozróżniają wielkich i małych liter).
Szczerze mówiąc, problemy z większością osób uczących programowania komputerowego polegają na tym, że od lat nie napisały linii kodu produkcyjnego i nie mają pojęcia, co właściwie robi działający inżynier oprogramowania. Poczekaj, aż zaczniesz pracować, a następnie zdecyduj, co uważasz za dobry pomysł, czy nie.
Nie uważam tego za złą praktykę. Konsekwencja jest jak zwykle królem.
Myślę, że chodzi o kontekst. W kontekście samej tabeli „id” oznacza dokładnie to, czego oczekujesz, etykietę, która pomoże jednoznacznie zidentyfikować ją na tle innych, które w przeciwnym razie mogą (lub wyglądać) identycznie.
W kontekście dołączeń Twoim obowiązkiem jest zbudowanie złączeń w taki sposób, aby były czytelne dla Ciebie i Twojego zespołu. Tak jak możliwe jest utrudnienie wyglądania przy złym frazowaniu lub nazywaniu, tak samo możliwe jest zbudowanie sensownego zapytania z efektywnym wykorzystaniem aliasów, a nawet komentarzy.
W ten sam sposób, w jaki klasa Java o nazwie „Foo” nie ma swoich właściwości z prefiksem „Foo”, nie czuję się zobowiązana do poprzedzania identyfikatorów tabel nazwami tabel. W kontekście zwykle jest jasne, do jakiego identyfikatora się odnosi.
BOOM, odpowiedź na pytanie.
Teraz powiedz swojemu nauczycielowi, że SO ćwiczy zły projekt bazy danych.
PostTypeId -> PostTypes.Id
; AcceptedAnswerId -> Answers.Id
; OwnerUserId -> Users.Id
. Dlaczego tak łatwą praktykę należy uważać za „złą”?
Utrudnia (i dezorientuje) wykonywanie naturalnego łączenia na stole, więc tak, to źle, jeśli nie bardzo źle.
Natural Join jest starożytnym artefaktem SQL Lore (tj. Algebry relacyjnej), którą mogłeś zobaczyć: perhaps być może w książce bazy danych. Mam na myśli to, że Natrual Join nie jest nowym, wymyślonym pomysłem SQL, chociaż wydawało się, że DBMS go wdrożyło w nieskończoność, dlatego nie jest to nowy wymarzony pomysł na wdrożenie go, może być nawet nierozsądne zignorowanie jego istnienie w dzisiejszych czasach.
Cóż, jeśli nazwiesz wszystkie identyfikatory klucza podstawowego, stracisz łatwość i prostotę naturalnego łączenia. select * from dudes natural join cars
trzeba będzie napisać select * from dudes inner join cars where cars.dudeid = dudes.id
lub select * from dudes inner join cars where dudes.carid = cars.id
. Jeśli jesteś w stanie wykonać naturalne połączenie, możesz zignorować rzeczywistą relację, która, moim zdaniem, jest niesamowita.
Jest sytuacja, w której umieszczenie „ID” na każdym stole nie jest najlepszym pomysłem: USING
słowo kluczowe, jeśli jest obsługiwane. Używamy go często w MySQL.
Na przykład, jeśli masz fooTable
kolumnę fooTableId
i barTable
klucz obcy fooTableId
, twoje zapytania mogą być skonstruowane jako takie:
SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)
Nie tylko oszczędza pisania, ale jest znacznie bardziej czytelny w porównaniu do alternatywy:
SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)
USING
kluczowe jest obsługiwane przez bazę danych postgres / mysql / sqlite, co oznacza mniej pisania, które niektóre inne odpowiedzi wymieniają jako powód do użycia id
, i ostatecznie, moim subiektywnym zdaniem, jest bardziej czytelne.
Dlaczego nie zapytać swojego nauczyciela?
Pomyśl o tym, gdy wszystkie kolumny PK nazwane są tabelami, ID
używanie ich jako kluczy obcych jest koszmarem.
Nazwy kolumn muszą mieć znaczenie semantyczne. ID
jest ogólny.
id
Samo nic nie znaczy, zwłaszcza w kontekście klucza obcego do innej tabeli. Nie ma to nic classes
wspólnego z dobrym podstawowym podstawowym projektem relacyjnej bazy danych.
table.id
jest całkowicie akceptowalnym sposobem odwoływania się do id
pola. Poprzedzanie nazwy pola nazwą tabeli jest zbędne.
Identyfikator jest zły z następujących powodów:
Jeśli wykonujesz wiele zapytań dotyczących raportowania, zawsze musisz alias kolumn, jeśli chcesz zobaczyć oba. Staje się więc stratą czasu, kiedy można nazwać go poprawnie na początku. Te złożone zapytania są wystarczająco trudne (piszę zapytania, które mogą mieć setki wierszy) bez dodatkowego obciążenia związanego z wykonywaniem niepotrzebnej pracy.
Może to powodować błędy w kodzie. Jeśli korzystasz z bazy danych, która pozwala na korzystanie z naturalnego sprzężenia (nie sądzę, że powinieneś go kiedykolwiek używać, ale gdy funkcje są dostępne, ktoś będzie ich używał), połączysz się z niewłaściwą rzeczą, jeśli uzyskasz programistę, który go używa.
Jeśli kopiujesz sprzężenia, aby utworzyć złożone zapytanie, łatwo zapomnieć o zmianie aliasu na żądany i uzyskać niepoprawne połączenie. Jeśli każdy identyfikator jest nazwany na podstawie tabeli, w której się on znajduje, zwykle pojawia się błąd składniowy. Łatwiej jest również wykryć, czy złożone zapytanie dołączenia jest niepoprawne, jeśli nazwa pPK i nazwa FK są zgodne.
ID
ogóle mnie nie przekonują.
Istnieją odpowiedzi, które podchodzą do tego, co uważam za najważniejszy powód, dla którego nie używam „id” jako nazwy kolumny klucza podstawowego w tabeli: mianowicie spójność i zmniejszona dwuznaczność.
Jednak dla mnie kluczową zaletą jest programista konserwacji, w szczególności ten, który nie był zaangażowany w pierwotne opracowanie. Jeśli używałeś nazwy „PersonID” dla identyfikatora w tabeli Person i konsekwentnie używałeś tej nazwy jako klucza obcego, napisanie zapytania do schematu jest banalne, aby dowiedzieć się, które tabele mają PersonID bez konieczności wnioskowania o tym „PersonID” to nazwa używana, gdy jest to klucz obcy. Pamiętaj, że dobre lub złe relacje między kluczami obcymi nie zawsze są egzekwowane we wszystkich projektach.
Istnieje przypadek skrajny, w którym jedna tabela może wymagać dwóch kluczy obcych do tej samej tabeli, ale w takich przypadkach wstawiłbym oryginalną nazwę klucza jako nazwę sufiksu dla kolumny, więc dopasowanie wieloznaczne,% PersonID, może łatwo znaleźć te przypadki również.
Tak, wiele z tego można osiągnąć dzięki standardowi posiadania „id” i wiedzy, aby zawsze używać go jako „tableNameID”, ale to wymaga zarówno znajomości, że praktyka jest na miejscu, a zależnie od pierwotnych programistów, aby postępować zgodnie z intuicyjna standardowa praktyka.
Chociaż niektórzy zauważyli, że do napisania dłuższych nazw kolumn potrzebne są dodatkowe naciśnięcia klawiszy, ale przypuszczam, że napisanie kodu to tylko niewielka część aktywnego życia programu. Jeśli celem było zapisanie naciśnięć klawiszy programisty, nigdy nie należy pisać komentarzy.
Jako ktoś, kto spędził wiele lat na utrzymywaniu dużych projektów z setkami tabel, zdecydowanie wolałbym spójne nazwy dla klucza między tabelami.
Companies
tabela ma 2 klucze obce do Persons
tabeli. Jeden reprezentuje prezesa firmy; drugi reprezentuje skarbnika spółki. Czy naprawdę nazwałbyś kolumny PersonID1
i PersonID2
? Nazwanie ich PresidentID
i byłoby znacznie bardziej opisowe TreasurerID
. O wiele łatwiej mi to czytać inner join Person AS Presidents ON Company.PresidentID = Presidents.ID
niżinner join Person AS Person1 ON Company.PersonID1 = Person1.PersonID
CompanyOfficer
lub, CompanyPerson
która pozwala na relację wiele do wielu pomiędzy Company
oraz Person
z dodatkowymi informacjami na temat charakteru relacji. Gdybym zaimplementował ją w Company
tabeli, użyłbym nazw kolumn PresidentPersonID
i TreasurerPersonID
zachowałby część * PersonID nazwy, dodając dodatkowy deskryptor. inner join Person as Presidents on Company.PresidentPersonID = Presidents.PersonID
Praktyka używania Id jako pola klucza podstawowego prowadzi do praktyki, w której identyfikator jest dodawany do każdej tabeli. Wiele tabel ma już unikalne informacje, które jednoznacznie identyfikują rekord. Użyj tego jako klucza podstawowego, a nie pola identyfikatora dodawanego do każdej tabeli. To jedna z podstaw relacyjnych baz danych.
I właśnie dlatego używanie id jest złą praktyką: id często nie jest informacją, tylko automatycznym wzrostem.
rozważ następujące tabele:
PK id | Countryid | Countryname
1 | 840 | United States
2 | 528 | the Netherlands
Co jest nie tak z tą tabelą, to to, że pozwala użytkownikowi dodać kolejną linię: Stany Zjednoczone, z Countrycode 840. Po prostu złamała integralność relacyjną. Oczywiście możesz wymusić unikalność na poszczególnych kolumnach lub możesz użyć klucza podstawowego, który jest już dostępny:
PK Countryid | Countryname
840 | United States
528 | the Netherlands
W ten sposób wykorzystujesz informacje, które już posiadasz jako klucz podstawowy, który jest sercem projektowania relacyjnych baz danych.
Nie uważam, że jest to zła praktyka, jeśli jest właściwie stosowana. Często zdarza się, że pole ID automatycznie zwiększa się o nazwie „ID”, którego nigdy nie trzeba dotykać, i używa bardziej przyjaznego identyfikatora dla aplikacji. Pisanie kodu może być trochę kłopotliwe, from tableA a inner join tableB b on a.id = b.a_id
ale kod ten można schować.
Jako osobistą preferencję staram się poprzedzać identyfikator nazwą jednostki, ale nie widzę prawdziwego problemu z używaniem tylko Id
wtedy, gdy jest obsługiwana w całości przez bazę danych.
Identyfikator jest na tyle powszechny, że nie sądzę, że mógłby to kogoś pomylić. Zawsze będziesz chciał poznać stół. Umieszczanie nazw pól w kodzie produkcyjnym bez dołączania tabeli / aliasu jest złą praktyką. Jeśli martwisz się, że możesz szybko pisać zapytania ad hoc, jesteś sam.
Mam tylko nadzieję, że nikt nie tworzy bazy danych SQL, w której ID jest słowem zastrzeżonym.
CREATE TABLE CAR (ID);
Dba o nazwę pola, klucz podstawowy i przyrosty automatyczne o 1, zaczynając od 1 wszystko w jednym ładnym małym zestawie 2 znaków. Och, nazwałbym to CARS, ale jeśli chcemy zaoszczędzić na naciśnięciach klawiszy i kto naprawdę myśli, że stół o nazwie CAR będzie miał tylko jeden?
Car
przedstawia miejsce, w Table
którym każdy Row
reprezentuje pojedynczy Car
. Wywołanie Cars
zmian semantycznych i pokazuje całkowity brak zrozumienia formalnych podstawowych zasad teorii relacyjnej. Szyny to doskonały przykład kogoś, kto wiedział wystarczająco dużo, aby być niebezpiecznym .
To pytanie było wielokrotnie powtarzane, ale pomyślałem, że ja też dodam swoją opinię.
Używam identyfikatora, co oznacza, że jest to identyfikator każdej tabeli, więc kiedy dołączam do tabeli i potrzebuję klucza podstawowego, automatycznie dołączam do klucza podstawowego.
Pole id jest autoinkrementacją, bez znaku (co oznacza, że nigdy nie muszę ustawiać jego wartości i nie może być ujemne)
W przypadku kluczy obcych używam tablenameid (znowu kwestia stylu), ale kluczem podstawowym, do którego dołączam, jest pole identyfikatora tabeli, więc spójność oznacza, że zawsze mogę łatwo sprawdzać zapytania
id też jest krótki i słodki
Dodatkowa konwencja - używaj małych liter dla wszystkich nazw tabel i kolumn, więc nie można znaleźć problemów z powodu wielkości liter
Inną rzeczą do rozważenia jest to, że jeśli nazwa klucza podstawowego różni się od nazwy klucza obcego, nie można używać niektórych narzędzi stron trzecich.
Na przykład nie można załadować schematu do narzędzia takiego jak Visio i uzyskać dokładne ERD.
Uważam, że ludzie tutaj zajmują się prawie każdym aspektem, ale chcę dodać, że „identyfikator” nie jest i nie powinien być odczytywany jako „identyfikator”, jest raczej „indeksem” i na pewno nie określa ani nie opisuje tożsamości wiersza. (Być może użyłem tutaj niewłaściwych sformułowań, popraw mnie, jeśli tak zrobiłem)
Mniej więcej tak ludzie czytają dane tabeli i jak piszą swój kod. Ja osobiście i najprawdopodobniej jest to najpopularniejszy sposób, w jaki częściej widzę, że koderzy piszą pełne referencje jako table.id
, nawet jeśli nie muszą robić związków i / lub dołączać. Na przykład:
SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>
W ten sposób możesz przetłumaczyć go na angielski jako „Daj mi kolor i model tego samochodu, który ma numer”. a nie jako „Daj mi kolor i model tego samochodu, który jest określony jako numer”. Identyfikator nie reprezentuje samochodu w żaden sposób, jest to tylko indeks samochodu, numer seryjny, jeśli wolisz. Tak jak wtedy, gdy chcesz pobrać trzeci element z tablicy.
Podsumowując, chciałem dodać, że jest to tylko kwestia preferencji, a opisany sposób czytania SQL jest najbardziej popularny.
Są jednak przypadki, w których nie jest to używane, na przykład (o wiele rzadszy przykład), gdy identyfikator jest ciągiem, który naprawdę opisuje. Na przykład id = "RedFordMustang1970"
lub coś podobnego. Naprawdę mam nadzieję, że mógłbym to wyjaśnić przynajmniej po to, aby uzyskać ten pomysł.