Jak przechowywać statusy rekordów (np. Oczekujące, kompletne, robocze, anulowane…)

18

Dość wiele aplikacji wymaga, aby rekordy w ich tabelach miały status, taki jak „kompletny”, „projekt”, „anulowany”. Jaki jest najlepszy sposób przechowywania tych statusów? Aby zilustrować, o co tu chodzi, to * bardzo krótki) przykład.

Mam prostą aplikację Blog, a każdy post ma status: opublikowany, szkic lub w toku.

Widzę to na dwa sposoby, aby to wymodelować w bazie danych.

  1. Tabela Post ma pole tekstowe zawierające tekst statusu.
  2. Tabela Post ma pole statusu, które zawiera identyfikator rekordu w tabeli PostStatus

Przykład blogu tutaj jest bardzo prostym przykładem. Gdzie może wystarczyć wyliczenie (jeśli jest obsługiwane). Chciałbym jednak, aby odpowiedzi na pytanie uwzględniały fakt, że lista statusów może się zmienić w dowolnym momencie, aby można było dodać lub usunąć więcej.

Czy ktoś może wyjaśnić zalety / wady każdego z nich?

Twoje zdrowie!

Moje pierwsze zdanie na ten temat polega na tym, że lepiej jest użyć innej tabeli i sprawdzić status jako lepszy dla normalizacji i zawsze uczono mnie, że normalizacja jest dobra dla baz danych

weganista
źródło
1
Zobacz także dba.stackexchange.com/q/11631/630
gbn
Co rozumiesz przez „w dowolnym momencie”? Czy to oznacza jako część aktywności użytkownika, czy jako część cyklu wydania oprogramowania?
kevin cline
Oba, w których przypadkach najlepiej zastosować jedno z wymienionych tu podejść. Więc jeśli użytkownicy będą mogli dodawać nowe statusy lub jeśli nowe zostaną dodane w późniejszym momencie projektu
weganista
Przechowywanie tekstu w bazie danych może być dobrą denormalizacją. Myślę, że może to zależeć od dokładnych szczegółów, np. Jak często Twoja organizacja zmienia swoje procesy (prowadząc do możliwych zmian statusu)?
Jaydee,
Jeśli użytkownicy mogą dodawać nowe statusy, to zupełnie inna sprawa. Prawdopodobnie będziesz chciał nagrać tworzącego użytkownika itp. Ze statusem i na pewno potrzebujesz innej tabeli.
kevin cline

Odpowiedzi:

14

Przechowywanie statusu jako indeksu w innej tabeli jest niepotrzebną komplikacją. Przechowuj status bezpośrednio w tabeli w czytelny sposób. W kodzie aplikacji użyj stałych lub typu wyliczenia. Spowoduje to uproszczenie kodu aplikacji i ułatwi debugowanie warstwy danych.

Nie denormalizuje to danych, jedynie zmienia reprezentację. Jeśli baza danych obsługuje wyliczenia bezpośrednio, użyj tego. W przeciwnym razie użyj ograniczenia, aby ograniczyć wartości kolumn. Będziesz mieć ograniczenie w obu kierunkach: albo bezpośrednie ograniczenie wartości kolumn, albo ograniczenie klucza obcego.

Tak, może być konieczne przedstawienie statusu w różny sposób dla różnych użytkowników. Jest to problem prezentacji, który należy rozwiązać w warstwie prezentacji, a nie w warstwie trwałości.

Kevin Cline
źródło
1
+1, Z wyjątkiem konkretnej potrzeby przechowywania listy statusów w bazie danych, jest to na ogół najprostszy i najmniej skomplikowany sposób, aby to zrobić.
GrandmasterB
2
Jest to w porządku, chyba że zaczniesz zmieniać architekturę statusu lub przechowywać daty mutacji
LastTribunal
10

Przechowywanie tekstu statusu nie jest dobrym pomysłem IMO, ponieważ ktoś może zdecydować, że zamiast tego należy nazwać „ukończony”, a następnie trzeba zaktualizować bazę danych, przejrzeć program, czy ktoś zakodował tekst na stałe itp.

W wielu programach widziałem albo kod numeryczny (1 = nowy, 2 = szkic, 3 = w sprawdzaniu poprawności, 4 = kompletny, 99 = anulowany) lub krótki kod alfanumeryczny („NOWOŚĆ”, „DRA”, „INV ”,„ COM ”,„ CAN ”). Później sprawia, że ​​kod (w programie lub w bazie danych) jest bardziej czytelny dla człowieka, co na ogół jest dobrą rzeczą. Z drugiej strony, kody numeryczne ułatwiają na przykład porównanie „większe niż” lub „mniejsze niż”

select * from myrecords where status < Status.Complete;
użytkownik 281377
źródło
Jakiś idiota może też podrobić identyfikator.
Morons
Kolejną zaletą identyfikatorów jest konieczność zapewnienia lokalizacji. Możesz użyć swojego identyfikatora, aby wyszukać ciąg zasobów i wyświetlić. W przypadku łańcuchów zakodowanych na
stałe
3
Nie sądzę, aby robienie statusów przy użyciu porównań „większych niż” lub „mniejszych niż”, takich jak pokazane, jest dobrym pomysłem. Może działać w prostszych aplikacjach, takich jak ten przykład, ale nie jest dobry w przypadku bardziej złożonych aplikacji (chociaż jestem pewien, że o tym
wiesz
1
@armitage: można wyszukiwać za pomocą ciągów. Nazwy zasobów to ciągi znaków:status.draft=Draught
kevin cline
veganista: Jasne, że porównania mogą być większe niż / mniejsze niż w porównaniu, ale widziałem duże, złożone systemy, które to robią i żyją.
user281377
4

Trzy zasady relacyjnych baz danych:

  1. Normalizować
  2. Normalizować
  3. Normalizować

Więc twoje pytanie samo odpowiada. Zachowaj status w jego własnej tabeli i używaj GUID / UUID jako identyfikatora . Indeksowane GUID są bardzo szybkie i rozwiązują problemy nieodłącznie związane ze zwiększaniem liczb. Dzięki identyfikatorowi możesz robić fajne rzeczy, np. Pytać DB o wszystkie ukończone posty za pomocą identyfikatora, a ponieważ pracujesz w ramach relacyjnego modelu db, jest to bardzo szybkie. Jeśli masz tylko pole, DB musi zapętlać każdy wiersz i porównywać tekst, być może z mungowaniem, a to jest bardzo wolne.

Nazwy statusu postu mogą się zmienić, więcej informacji o statusie postu może wejść do tabeli, wszystko działa po normalizacji .

Na przykład możesz dodać poziomy statusu jako dodatkowe informacje, które pozwoliłyby na porównanie wzmianek o amunicji. Ale nie zależą one od klucza do pozycjonowania, umożliwiając zmianę poziomu statusu bez szkody dla integralności DB. Możesz także wstawić dodatkowe poziomy, co jest dość trudne, jeśli poziom jest powiązany z kluczem autoinkrementacji.

Spencer Rathbun
źródło
Powody, które tu podałeś, są dokładnie tymi, dla których używam innego stołu do przechowywania moich przerw. Głównym powodem, dla którego zadałem to pytanie, jest sprawdzenie, czy czasem warto skorzystać z prostszego pola tekstowego.
weganista
@Liam Tylko jeśli normalizuje się do pola tekstowego. To znaczy, jeśli twoje pole tekstowe zależy tylko od klucza podstawowego, a ty szukasz rzeczy na podstawie klucza podstawowego , a pole tekstowe się pojawi. Relacyjna baza danych dotyczy relacji, masz ją tutaj, więc należy ją zdefiniować. Jednym z niewielu wyjątków jest to, że przetwarzasz brudne dane ze źródła zewnętrznego i nie masz czasu na ich pełne modelowanie. Unikaj tego, jeśli to możliwe.
Spencer Rathbun
ukrywa oczy, opłakując
GUIDY
Powinieneś napisać „trzy teorie relacyjnych baz danych”. Teoria nie zawsze jest praktyczna. Często bardziej efektywne jest przechowywanie kodu stanu bezpośrednio w rekordzie, z którym jest powiązany. Jeśli nie musisz go sprawdzać, aby go użyć, usunięcie sprzężenia z inną tabelą pozwala zaoszczędzić wiele zmarnowanego przetwarzania.
Suncat2000,
Odebrano z powodu złych informacji o typach kolumn w porównaniu do pełnych skanów tabeli.
Igorrs
3

Tak, powinieneś wybrać opcję 2, mając tabelę PostStatus.

Oprócz wszystkich zalet wymienionych w innych odpowiedziach.

Pamiętając, że statusy należy dodać lub usunąć, możesz mieć kolumnę „włączone” w tabeli PostStatus, więc jeśli status zostanie usunięty, zaznacz kolumnę „włączone” jako „N”, w ten sposób będziesz mógł dodaj lub usuń statusy, a także istniejące rekordy pozostaną bez problemów.

Pan Spark
źródło
1

Chciałbym dodać do wnikliwych odpowiedzi, które dla pełnej normalizacji zmiana statusu bytu jest faktycznie modelowana w osobnym bycie, np. O nazwie „statusChange”.

Potrzebujesz dodatkowego przyłączenia do encji statusChange, ale zyskujesz możliwość dodania dodatkowych informacji, takich jak aktor dokonujący zmiany, możliwe komentarze na temat przyczyny zmiany oraz data, w której statusChange jest wykonywany, a być może nawet kiedy staje się skuteczne.

Dibbeke
źródło
0

Użycie tekstu jako statusu w tabeli rekordów prawdopodobnie nie byłoby dobrym pomysłem, ponieważ może się to zmienić i trudno byłoby przeprowadzić kontrolę integralności danych podczas wstawiania / aktualizacji. Jeśli korzystasz z DBMS z typem danych enum, możesz użyć tego zamiast tego (wydajność prawdopodobnie nie zostanie obniżona ... zależnie).

Jeśli twój status wymaga metadanych (opisu, utworzonego przez przyjazną nazwę, ...), musisz przechowywać statusy w osobnej tabeli i mieć klucz statusu w swojej tabeli rekordów (upewnij się, że używasz klucza obcego). Identyfikator niekoniecznie musi być liczbą, tylko PK tabeli statusu. Ponadto, jeśli statusy znajdują się we własnej tabeli, możesz je udostępnić dla różnych typów rekordów (tabel), jeśli dotyczy. Nie martwiłbym się problemami z wydajnością z JOIN do tabeli statusu.

Cokolwiek zrobisz, unikaj magicznych stanów (1 dla aktywnych, 2 dla usuniętych, ...). Opiera się to na dokumentacji i tradycji, które zawsze mają tendencję do zagubienia się na wystarczająco dużej osi czasu. Jeśli w ogóle używasz identyfikatorów numerycznych, upewnij się, że gdzieś w bazie danych istnieje powiązanie tekstowe.

smp7d
źródło
Jeśli nie martwisz się wydajnością, prawdopodobnie poświęcasz skalowalność. Komputery nie mogą uniknąć magicznych stanów: 0 i 1 są z natury magiczne.
Suncat2000,
0

Zależy od celu projektu bazy danych.

Jeśli projektujesz bazę danych tak, aby obsługiwała aplikację (tj. Obiekty (kod) są nadrzędne dla wszystkich), to używając wyliczenia (lub wyliczenia psuedo dla klas, które ich nie obsługują) i zapisując nazwę wyliczenia jest dobry pomysł, ponieważ nadal kontrolujesz wartości dozwolone przez wyliczanie, a także czynisz tabelę nieco łatwiejszą do odczytania, gdy jesteś zmuszony przeglądać surowe dane (co nie jest tak często, jeśli kod faktycznie rządzi wszystkim). Ale jeśli wyliczenie jest oflagowane. Następnie zwykle przechowuję wartość wyliczoną (liczbę całkowitą).

ElGringoGrande
źródło
-1

Status jest bardzo ważny, za każdym razem, gdy otrzymujesz informacje o wpisie, musisz uzyskać jego status, lub będziesz chciał filtrować posty według statusu. Jeśli masz status w innej tabeli, musisz wykonać połączenia, aby uzyskać te informacje, co obniży wydajność. Zdecydowanie powinieneś mieć status w tej samej tabeli. I umieść na nim indeks! Nadal możesz używać liczb całkowitych jako statusu lub pola enum.

dxvargas
źródło
-2

Prawidłowym rozwiązaniem jest użycie magazynu zdarzeń / źródła z CQRS lub blockchain. Problem z przechwytywaniem zdarzeń w RDB polega na tym, że RDB przechowuje migawkę pojedynczego zdarzenia w czasie, a rzeczy takie jak „Statusy / Stany” są sekwencją mutacji, które ewoluują w czasie

LastTribunal
źródło
Jeśli zamierzasz obniżyć głosowanie na mój post, to zrób sprawę. W przeciwnym razie jesteś po prostu łagodnym lemingiem, który ma bardzo niewielki zasięg poza pudełkiem
LastTribunal 12.04.18