Jaki jest skuteczny sposób oznaczania kolumn w bazie danych?

30

Kiedyś oznaczałem kolumny w moich bazach danych w następujący sposób:

user_id
user_name
user_password_hash

Aby uniknąć konfliktów podczas łączenia dwóch tabel, ale potem dowiedziałem się więcej o tym, jak aliasować tabele, i przestałem to robić.

Jaki jest skuteczny sposób oznaczania kolumn w bazie danych? Czemu?

Thomas O
źródło
Która baza danych To, jak oznaczam etykietę w Oracle, różni się od większości innych baz danych ze względu na to, że automatycznie wybiera kolumny, na których mają się opierać połączenia, jeśli nazwy są zgodne.
Joe
@Joe, Cóż, zawsze korzystałem z MySQL i SQLite3, ale powinien on mieć zastosowanie do większości innych baz danych.
Thomas O
@joe nigdy nie zauważył, że Oracle jest inny. Czy możesz podać link?
bernd_k
@bernd_k: Dodałem kilka linków do mojej odpowiedzi , poniżej
Joe

Odpowiedzi:

33

W twoim przypadku użytkownik prefiksu jest zbędny. My (twórcy) wiemy, że to użytkownik tabeli, więc po co dodawać user_prefiks przed każdym polem?

Sugeruję, abyś zrobił to w bardziej naturalny sposób.

Jakie są cechy charakterystyczne osoby: nazwisko, imię, data urodzenia, obywatelstwo itp.

Jakie są cechy samochodu: model, rok, kolor, energia itp.

Twoja kolumna powinna być nazwana tak naturalnie, jak to możliwe, dzięki czemu schemat będzie bardziej przejrzysty dla wszystkich, dla ciebie i tych, którzy będą po tobie. Nazywa się to również fazą konserwacji i zwykle wszystko, co możesz zrobić, aby ułatwić konserwację, jest warte wysiłku.

Spredzy
źródło
1
Tak, denerwuje mnie, gdy ludzie to robią. Również, gdy wywołują całą swoją tabelę tbl_whokolwiek.
Gajusz
Odnosi się to również do pojęcia „słów klasowych” i wydaje się, że w społeczeństwie toczy się debata, kiedy słowa klasowe są i nie są odpowiednie. (słowo klasy jest narzędziem do: zidentyfikowania odrębnej kategorii lub klasyfikacji danych, określenia rodzaju danych opisywanych przez nazwę danych i opisania głównej klasyfikacji danych związanych z elementem danych).
Jon Schoning
17

Oprócz komentarza Spredzy, oznacz swoje klucze podstawowe tym samym (ID), aby podczas pisania zapytań w locie można było łatwo przywołać (u.ID = c.ID) zamiast konieczności wyszukiwania „Czy to countryID , country_ID, country_ID, countryID,? ”

David Hall
źródło
5
Kiedyś pracowałem nad bazą danych, w której DBA zdecydowało się użyć identyfikatora w niektórych tabelach i identyfikatora w innych, a MySQL skonfigurowano tak, aby rozróżniał wielkość liter ... zabawne czasy!
Toby
6
Zwykle używamy tablename.tablename_id. Np. Car.car_id; person.person_id. Nazwy osobliwe dla tabel.
glasnt
@glasnt inteligentna decyzja.
garik
1
To w rzeczywistości bardzo zły pomysł i stracisz możliwość korzystania z USINGklauzuli SQL (jest to niezgodne ze specyfikacją).
Evan Carroll
9

Nie mogłem się bardziej zgodzić z uzupełnieniem Davida Halla do doskonałej odpowiedzi Spredzy. Prosta i naturalna jest droga. Pomyłka przy stole nie powinna stanowić problemu, jeśli nazywasz także tabele w sposób naturalny.

Nie ma sensu mieć users.user_id i cars.car_id, kiedy można mieć users.id i cars.id

bsoist
źródło
7

Twierdziłbym, że w schemacie bazy danych każda kolumna powinna mieć unikalną nazwę we wszystkich tabelach. Jest tego kilka przyczyn:

  • Z modelowego punktu widzenia: zaczynasz od zupy atrybutów i normalizujesz ją do tabel. Z czasem możesz dalej denormalizować lub normalizować lub wprowadzać widoki lub zmaterializowane widoki lub wprowadzać nowe tabele. Nie stanowi to nigdy problemu, jeśli wszystkie nazwy kolumn są unikalne.

  • Możesz użyć tego dołączyć składni: a JOIN b USING (a_id) JOIN c USING (a_id). Bardzo wygodne, a także pomaga w następującym punkcie.

  • Jeśli uruchamiasz zapytania z dużą SELECT *liczbą sprzężeń lub tworzysz zmaterializowane widoki , nigdy (cóż, być może rzadko) występuje konflikt. Myśleć o przyłączeniu person.name, product.name, country.nameitp Urgh.

  • Ogólnie rzecz biorąc, jeśli masz duże zapytania, trudno jest śledzić, co idoznacza wszędzie.

Peter Eisentraut
źródło
Jak nazwałbyś na przykład kolumnę nazwiskiem pracownika i nazwą witryny? Jak można uniknąć nadmiarowości kolumny z etykietą nazwy?
Spredzy
@Spredzy: Po prostu bym zwolnił.
Peter Eisentraut,
1
Odpowiedź na te obawy: aliasy.
Jon of All Trades,
7

Zobaczmy, na twoim przykładzie będzie to wyglądać mniej więcej tak:

USERS
----
id
username,
password
registration_date

Używam nazwy tabeli wielkimi literami. To pozwala mi łatwo zidentyfikować tabelę. Kolumny, które właśnie wymieniłem, dotyczą tego, co reprezentują. Staram się nie używać cyfr ani dołączać do nich żadnego prefiksu lub sufiksu. To sprawi, że zapytania będą martwe, proste i całkiem proste.

BTW, myślę, że powinieneś znaleźć jakiś styl, który ci się podoba i trzymać się go. Jeśli często go zmieniasz, będziesz mieć bałaganszy schemat DB.

eiefai
źródło
+1 za „znajdź styl, który ci się podoba i trzymaj się go”. Spójność jest lepsza niż dokładne przestrzeganie jakiejkolwiek konkretnej normy (chociaż jeśli jeszcze nie wybrałeś normy, niektóre są lepsze niż inne).
Jon of All Trades,
5

Podobnie jak inne, zalecam, aby nie dołączać nazwy tabeli jako części kolumny. Chyba, że ​​masz setki tabel z przeważnie podobnymi nazwami kolumn: jeśli masz wiele tuzinów tabel z kolumnami o tytule ID, to z całą pewnością poprzedzaj je nazwą tabeli.

Niedawno opuściłem firmę, w której jeden z programistów wolał prefiksować kolumny klucza podstawowego i klucza obcego pk i fk. Doprowadziło to do niektórych obrzydliwości, w których kolumny zaczynały się od pkfk (zwykle złożony klucz podstawowy oparty na 2 kolumnach, z których jedna kolumna była kluczem obcym do innej tabeli).

Tangurena
źródło
4
czy to się liczy jako fk_cluster?
Kaji,
5

Pracuję w środowisku, w którym nazwa każdej kolumny zaczyna się od przedrostka pochodzącego od nazwy tabeli, to nie jest mój wynalazek, ale jestem z niego całkiem zadowolony.

Idealnie nazwy kolumn są unikalne dla wszystkich tabel w bazie danych.

Niektóre spostrzeżenia:

  • potrzebujemy tylko aliasów tabel, gdy tabele są łączone wiele razy w instrukcji select
  • zapobiega to niektórym błędom podczas kopiowania fragmentów kodu, ponieważ nazwy kolumn muszą być dostosowane do nazwy tabeli
  • pomaga pokazać, do której tabeli wskazuje kolumna klucza obcego

Ogólne pomysły: Najważniejsza jest spójność każdej konwencji nazewnictwa: - liczba pojedyncza vs. liczba mnoga (ok, dotyczy to tabel, a nie kolumn) - identyfikacja kluczy głównych i obcych (budują strukturę względem zawartości bazy danych) - być spójna, gdy przechowujesz ciągi i krótki wariant tego samego ciągu - zachowaj spójność z flagami, statusem itp.

bernd_k
źródło
3

Zgadzam się z odpowiedzią Spredzy, ale dodam, że jako preferencję użyłbym camelCase zamiast under_score.

imię, nazwisko itp.

Toby
źródło
2
-1, ponieważ CamelCase nie działa we wszystkich systemach baz danych i nie określono systemu baz danych. Na przykład zła wiadomość o korzystaniu z CamelCase w Oracle (wymagałoby to użycia podwójnych cudzysłowów, aby go utworzyć, ale odtąd wszyscy uzyskujący do niego dostęp musieliby przeskakiwać przez obręcze, aby uzyskać do niego dostęp). Co za koszmar.
ScottCher
@ScottCher - Nie wiedziałem, że to nie działa w Oracle, ale nie jestem Oracle DBA. Wydawało mi się, że należy wziąć pod uwagę, że nazwy kolumn muszą najpierw być zgodne z zasadami określonymi przez dany DBS.
Toby
3

W przypadku Oracle, będziemy chcieli, aby nie nazwać kolumn „id” lub „name” lub coś rodzajowe.

Problem polega na tym, że domyślnie w starszych wersjach Oracle będzie próbować łączyć tabele na podstawie podobnych nazw kolumn, więc jeśli wszystko dobrze nazwałam, to ostatecznie skończyłem też na określeniu domyślnej klauzuli łączenia między moimi tabelami.

Ale nawet jeśli nie używasz Oracle, nie wybierając nazw pojawiających się w wielu tabelach, oznacza to również, że nie musisz wtedy męczyć się z aliasingiem za każdym razem, gdy musisz dokonać wyboru w dwóch tabelach:

SELECT
  instrument.name as instrument_name,
  instrument.abbr as instrument_abbr,
  source.name     as source_name,
  source.abbr     as source_abbr,
  ...
FROM ...

Jeśli więc wybór wielu tabel jest normą, dłuższe nazwy kolumn oszczędzają pisanie. (jeśli używasz tylko jednej tabeli na raz ... czy naprawdę potrzebujesz relacyjnej bazy danych?)

... a oszczędzanie na pisaniu prowadzi nas do kolejnego problemu w Oracle - przynajmniej w 8i (obecna wersja, kiedy wziąłem kursy Oracle SQL Tuning i Data Modeling) buforowanie planów wykonania opiera się tylko na pierwszych tak wielu znakach zapytanie (nie pamiętasz dokładnej wartości ... 1024?), więc jeśli masz zapytania, które różnią się tylko czymś na końcu klauzuli where i naprawdę długą listę wyodrębnianych kolumn, możesz może trafić w wydajność, ponieważ nie może poprawnie buforować planu wykonania.

Oracle miał przewodnik na temat wybierania, jak twierdzą, dobrych nazw tabel i kolumn, co jest w zasadzie przewodnikiem usuwania liter, dopóki nie zawierają około 5-8 znaków, ale nigdy tak bardzo mi na tym nie zależało.

...

Gdy sprawy potoczą się inaczej:

  • kolumny są zawsze pojedyncze (tabele są zawsze w liczbie mnogiej)
  • wszystkie nazwy są pisane małymi literami, na wypadek, gdyby było w nich rozróżniana wielkość liter
  • w wyniku powyższego użyj podkreślników zamiast wielbłąda.

aktualizacja : dla tych, którzy nie są zaznajomieni z zachowaniem łączenia Oracle, zobacz ostatni przykład Mastering Oracle SQL: Join Warunki , w którym wspomniano:

Co się stało? Powodem jest to, że oprócz dostawcy_id te dwie tabele mają inną parę kolumn o wspólnej nazwie. Ta kolumna to nazwa. Tak więc, gdy poprosisz o naturalne połączenie między dostawcą a tabelami części, połączenie odbywa się nie tylko poprzez zrównanie kolumny dostawca_id dwóch tabel, ale także kolumnę nazwy z dwóch tabel. Ponieważ żadna nazwa dostawcy nie jest taka sama jak nazwa części od tego samego dostawcy, zapytanie nie zwraca żadnych wierszy.

Zgodnie ze „starą składnią złączenia” (8i i wcześniejsze) „NATURAL JOIN” było domyślnym zachowaniem łączenia i uważam, że nadal tak jest, jeśli nie określisz warunku łączenia. Kiedyś „NATURAL JOIN” było oficjalną opcją w 9i, ogólną rekomendacją było, aby jej nie używać , ponieważ złe nazewnictwo kolumn może cię zepsuć, co jest moim zaleceniem dla dobrych nazw kolumn.

Joe
źródło
4
Mówisz o „naturalnych połączeniach” w drugim akapicie? Jeśli tak, SHUDDER ... Gdy tylko jest to możliwe, powinieneś określić, w jaki sposób system baz danych ma dołączać do twoich tabel. Pozostawienie decyzji w bazie danych może dać nieoczekiwane / niespójne wyniki. Ponadto połączenia naturalne są ograniczone do połączeń między dwiema tabelami, a zatem są względnie ograniczone pod względem użyteczności.
ScottCher,
2
NATURAL JOIN nigdy nie był domyślny. Jeśli nie podano / nie podano jednoznacznego łączenia, połączenie kartezjańskie zostanie wykonane (tj. Każdy wiersz w tabeli połączony z każdym wierszem w drugiej tabeli). Przed obsługiwaniem złączeń ANSI (tj. Tych określonych w klauzuli FROM) złączenia musiały być wykonywane w klauzuli WHERE.
Gary,
1
-1 dla naturalnych połączeń. Kiedy niezwiązana zmiana schematu może przerwać połączenia, lub jeszcze gorzej, zmienić je bez powodowania błędów, czeka Cię świat bólu. Pomyślcie o dzieciach i ZAWSZE określcie pola przyłączenia.
Jon of All Trades,
2
@ScottCher: „Pozostawienie decyzji do bazy danych” - po pierwsze, prawdopodobnie oznacza to raczej „DBMS” niż „bazę danych”. Po drugie, nie ma sztucznej inteligencji ani mechanizmu antropomorficznego w Oracle; jest raczej NATURAL JOINdeterministyczny.
poniedziałek
1
@Joe cross joinjest, był i zawsze będzie domyślny. Oracle nigdy nie pasowało do nazwy kolumny, chyba że natural joinzostało to jawnie użyte
Jack Douglas
1
  1. Nigdy nie używaj podwójnych cudzysłowów, "ponieważ w ten sposób zastępujesz natywne składanie baz danych w bazie danych. Specyfikacja SQL wymaga, aby wszystkie identyfikatory były złożone na wielkie litery. Niektóre bazy danych, takie jak PostgreSQL, składają je na małe litery. Jeśli nic nie jest cytowane, będzie działać we wszystkich bazach danych i mogą je złożyć do specyfikacji lub wartości domyślnej specyficznej dla rdbms.
  2. Użyj under_score ( _), ponieważ jak wyżej - nie powinieneś używać camelCase.
  3. użyj {entity}_iddla identyfikatorów (i kluczy obcych wskazujących na te identyfikatory). Ponieważ wtedy możesz użyć USINGklauzuli. Unikatowe na całym świecie nazwy kluczy używane w warunkach łączenia są konwencją ustanowioną w specyfikacji.

    SELECT *
    FROM employee
    INNER JOIN department
      USING (department_id);
    
      -- compare to
      ON employee.department_id = department.department_id;
Neil McGuigan
źródło
1
Zaktualizowałem to, aby było bardziej wyraźne.
Evan Carroll