Speichern von Datensatzstatus (wie Ausstehend, Vollständig, Entwurf, Abgebrochen ...)

16

Bei vielen Anwendungen müssen Datensätze in ihren Tabellen den Status "Vollständig", "Entwurf", "Abgebrochen" haben. Wie können diese Status am besten gespeichert werden? Um zu veranschaulichen, was ich hier vorhabe, ist ein * sehr kurzes) Beispiel.

Ich habe eine einfache Blog-Anwendung und jeder Beitrag hat den Status "veröffentlicht", "Entwurf" oder "Ausstehend".

So wie ich es sehe, gibt es zwei Möglichkeiten, dies in der Datenbank zu modellieren.

  1. Die Post-Tabelle verfügt über ein Textfeld, das den Statustext enthält.
  2. Die Post-Tabelle verfügt über ein Statusfeld, das die ID eines Datensatzes in der PostStatus-Tabelle enthält

Das Blog-Beispiel hier ist ein sehr einfaches Beispiel. Wo eine Aufzählung (falls unterstützt) ausreichen könnte. Bei der Beantwortung der Frage möchte ich jedoch berücksichtigen, dass sich die Liste der Status jederzeit ändern kann, sodass weitere hinzugefügt oder entfernt werden können.

Kann jemand die Vor- / Nachteile der einzelnen erklären?

Prost!

Meine anfängliche Meinung dazu ist, dass es besser ist, eine andere Tabelle zu verwenden und den Status als besser für die Normalisierung nachzuschlagen, und mir wurde immer beigebracht, dass die Normalisierung für Datenbanken gut ist

veganista
quelle
Was meinst du mit "jederzeit"? Bedeutet das als Teil der Benutzeraktivität oder als Teil des Software-Release-Zyklus?
Kevin Cline
In beiden Fällen wird einer der hier genannten Ansätze am besten verwendet. Wenn Benutzer also in der Lage sind, neue Status hinzuzufügen, oder wenn zu einem späteren Zeitpunkt im Projekt neue hinzugefügt werden
veganista
Das Speichern des Textes in der Datenbank kann eine gute Denormalisierung sein. Ich denke, es kann von genauen Details abhängen, zB Wie oft ändert Ihre Organisation ihre Prozesse (was zu möglichen Statusänderungen führt)?
Jaydee
Wenn Benutzer neue Status hinzufügen können, ist dies eine ganz andere Sache. Sie möchten wahrscheinlich den erstellenden Benutzer usw. mit dem Status aufzeichnen und benötigen definitiv eine andere Tabelle.
Kevin Cline

Antworten:

13

Das Speichern des Status als Index in einer anderen Tabelle ist eine unnötige Komplikation. Speichern Sie den Status lesbar direkt in der Tabelle. Verwenden Sie im Anwendungscode Konstanten oder einen Aufzählungstyp. Dies führt zu einem einfacheren Anwendungscode und erleichtert das Debuggen der Datenschicht.

Dadurch werden die Daten nicht denormalisiert, sondern lediglich die Darstellung geändert. Wenn die Datenbank Aufzählungen direkt unterstützt, verwenden Sie diese. Verwenden Sie andernfalls eine Einschränkung, um die Spaltenwerte einzuschränken. Sie haben entweder eine direkte Einschränkung für die Spaltenwerte oder eine Fremdschlüsseleinschränkung.

Ja, möglicherweise müssen Sie den Status für verschiedene Benutzer unterschiedlich darstellen. Dies ist ein Präsentationsproblem, das in der Präsentationsschicht und nicht in der Persistenzschicht gelöst werden muss.

Kevin Cline
quelle
1
Vorbehaltlich einer bestimmten Anforderung, die Liste der Status in der Datenbank zu führen, ist dies im Allgemeinen die einfachste und unkomplizierteste Möglichkeit, dies zu tun.
GroßmeisterB
2
Dies ist in Ordnung, es sei denn, Sie ändern die
Statusarchitektur
9

Das Speichern des Statustextes ist IMO keine gute Idee, da jemand entscheiden könnte, dass "vollständig" stattdessen als "fertig" bezeichnet werden soll, und Sie dann Ihre Datenbank aktualisieren müssen, das Programm durchsehen, wenn jemand den Text fest codiert hat usw.

Was ich in vielen Programmen gesehen habe, ist entweder ein numerischer Code (1 = neu, 2 = Entwurf, 3 = in Validierung, 4 = vollständig, 99 = storniert) oder ein kurzer alphanumerischer Code ("NEW", "DRA", "INV") "," COM "," CAN "). Letzteres macht den Code (im Programm oder in der Datenbank) besser lesbar, was im Allgemeinen eine gute Sache ist. Andererseits machen es numerische Codes einfach, Vergleiche beispielsweise "größer als" oder "kleiner als" durchzuführen

select * from myrecords where status < Status.Complete;
user281377
quelle
Einige Idioten können die ID auch hardcore.
Morons
Ein weiterer Vorteil von IDs besteht darin, dass Sie die Lokalisierung bereitstellen müssen. Sie können Ihre ID verwenden, um die Ressourcenzeichenfolge nachzuschlagen und anzuzeigen. Mit fest codierten Zeichenketten ist dies nicht möglich
armitage
3
Ich denke nicht, dass es eine gute Idee ist, Status mit "größer als" oder "kleiner als" zu vergleichen. Es funktioniert möglicherweise für einfachere Anwendungen wie dieses Beispiel, ist jedoch nicht für komplexere Anwendungen
geeignet
1
@armitage: Es ist durchaus möglich, eine Suche mit Strings durchzuführen. Ressourcennamen sind Zeichenfolgen:status.draft=Draught
Kevin Cline
veganista: Sicher, es kann Schwierigkeiten mit größeren als / kleineren als Vergleichen geben, aber ich habe große, komplexe Systeme gesehen, die das tun und leben.
user281377
3

Die drei Regeln relationaler Datenbanken:

  1. Normalisieren
  2. Normalisieren
  3. Normalisieren

Ihre Frage beantwortet sich also von selbst. Behalten Sie den Status in der eigenen Tabelle und verwenden Sie GUID / UUIDs als Ihre ID . Indizierte GUIDS sind sehr schnell und beheben die Probleme, die mit der Erhöhung von Zahlen verbunden sind. Mit einer ID können Sie coole Dinge tun, wie die DB nach allen abgeschlossenen Posts mit der ID zu fragen, und da Sie innerhalb des relationalen DB-Paradigmas arbeiten, ist es sehr schnell. Wenn Sie nur ein Feld haben, muss die DB jede einzelne Zeile durchlaufen und einen Textvergleich durchführen, möglicherweise mit Munging, und das ist sehr langsam.

Die Post-Status-Namen können sich ändern, weitere Informationen zum Post-Status können in die Tabelle aufgenommen werden. Alles funktioniert nur, wenn Sie normalisieren .

Beispielsweise können Sie Statusebenen als zusätzliche Informationen hinzufügen, die den Vergleich von ammoQ-Erwähnungen ermöglichen. Sie hängen jedoch nicht vom Positionierungsschlüssel ab, sodass die Statusebene neu angeordnet werden kann, ohne die Integrität der Datenbank zu beeinträchtigen. Sie können auch zusätzliche Ebenen einfügen. Dies ist ein ziemlicher Trick, wenn Sie die Ebene haben, die dem Autoincrementing-Schlüssel zugeordnet ist.

Spencer Rathbun
quelle
Die Gründe, die Sie hier angegeben haben, sind genau die Gründe, warum ich eine andere Tabelle verwende, um meine Pausen zu speichern. Der Hauptgrund, warum ich diese Frage gestellt habe, ist zu sehen, ob es manchmal gut ist, ein einfacheres Textfeld zu verwenden.
Veganista
@Liam Nur wenn es sich auf ein Textfeld normalisiert. Das heißt, wenn Ihr Textfeld nur vom Primärschlüssel abhängt und Sie nachschlagen basierend auf dem Primärschlüssel nachschlagen , wobei das Textfeld mitkommt. In einem relationalen DB geht es um Beziehungen. Sie haben hier eine Beziehung, daher muss sie definiert werden. Eine der wenigen Ausnahmen besteht darin, dass Sie schmutzige Daten von einer externen Quelle verarbeiten und nicht die Zeit haben, diese vollständig zu modellieren. Vermeiden Sie dies wenn möglich.
Spencer Rathbun
versteckt die Augen und trauert um die GUIDs, die niemals zurückkehren werden
sq33G
Sie sollten "drei Theorien relationaler Datenbanken" geschrieben haben. Theorie ist nicht immer praktisch. Oft ist es effizienter, einen Statuscode direkt in dem Datensatz zu speichern, auf den er sich bezieht. Wenn Sie es nicht nachschlagen müssen, um es zu verwenden, erspart das Entfernen der Verknüpfung zu einer anderen Tabelle viel verschwendete Verarbeitung.
Suncat2000
Abgestuft wegen falscher Informationen zu Spaltentypen im Vergleich zu vollständigen Tabellenscans.
Iglus
2

Ja, Sie sollten Option 2 wählen und eine PostStatus-Tabelle haben.

Abgesehen von all den Vorteilen, die in anderen Antworten erwähnt wurden.

Beachten Sie, dass die Status hinzugefügt oder entfernt werden müssen. In der PostStatus-Tabelle kann eine Spalte "Aktiviert" angezeigt werden. Wenn der Status entfernt wird, markieren Sie die Spalte "Aktiviert" als "N". Auf diese Weise können Sie dies tun Das Hinzufügen oder Entfernen von Status und auch die vorhandenen Datensätze bleiben ohne Probleme.

Mr Spark
quelle
1

Zu den ansonsten aufschlussreichen Antworten möchte ich hinzufügen, dass für eine vollständige Normalisierung eine Änderung des Status einer Entität tatsächlich in einer separaten Entität modelliert wird, z. B. mit dem Namen "statusChange".

Sie benötigen eine zusätzliche Verknüpfung mit der statusChange-Entität, haben jedoch die Möglichkeit, zusätzliche Informationen hinzuzufügen, z. B. den Akteur, der die Änderung ausführt, mögliche Kommentare zum Grund für die Änderung und ein Datum, an dem die statusChange durchgeführt wird, und möglicherweise sogar wann es wird wirksam.

Dibbeke
quelle
0

Die Verwendung von Text für den Status in der Datensatztabelle ist wahrscheinlich keine gute Idee, da sich dies ändern kann und es schwierig ist, Datenintegritätsprüfungen beim Einfügen / Aktualisieren durchzuführen. Wenn Sie ein DBMS mit einem Aufzählungsdatentyp verwenden, können Sie diesen stattdessen verwenden (Leistung wird wahrscheinlich nicht beeinträchtigt ... abhängig).

Wenn für Ihren Status Metadaten (Beschreibung, Erstellt von, Anzeigename, ...) erforderlich sind, müssen Sie den Status in einer separaten Tabelle speichern und einen Statusschlüssel in Ihrer Datensatztabelle haben (stellen Sie sicher, dass Sie einen Fremdschlüssel verwenden). Die ID muss nicht unbedingt eine Zahl sein, sondern nur die PK der Statustabelle. Wenn sich die Status in einer eigenen Tabelle befinden, können Sie sie gegebenenfalls für mehrere Datensatztypen (Tabellen) freigeben. Ich würde mir keine Sorgen um Leistungsprobleme machen, wenn Sie der Statustabelle beitreten.

Vermeiden Sie auf jeden Fall magische Zustände (1 für aktiv, 2 für gelöscht, ...). Dies beruht auf Dokumentation und Tradition, die immer dazu neigen, sich auf einer ausreichend großen Zeitachse zu verlaufen. Wenn Sie überhaupt numerische IDs verwenden, vergewissern Sie sich, dass irgendwo in Ihrer Datenbank eine Textverknüpfung vorhanden ist.

smp7d
quelle
Wenn Sie sich keine Sorgen um die Leistung machen, verlieren Sie wahrscheinlich die Skalierbarkeit. Es ist für Computer unmöglich, magische Zustände zu vermeiden: 0 und 1 sind von sich aus magisch.
Suncat2000
0

Hängt vom Zweck des Datenbankentwurfs ab.

Wenn Sie die Datenbank einfach so entwerfen, dass sie die Anwendung unterstützt (dh die Objekte (der Code) sind der Master aller), ist die Verwendung einer Aufzählung (oder einer Pseudo-Aufzählung für Klassen, die diese nicht unterstützen) und das Speichern des Namens der Aufzählung a Eine gute Idee, da Sie immer noch die Werte kontrollieren, die durch die Aufzählung zulässig sind, und die Tabelle ein wenig leichter lesbar machen, wenn Sie gezwungen sind, die Rohdaten anzuzeigen (was nicht so häufig der Fall ist, wenn der Code tatsächlich alle regiert). Aber wenn die Aufzählung markiert ist. Dann speichere ich in der Regel den Enum-Wert (Integer) ab.

ElGringoGrande
quelle
-1

Der Status ist sehr wichtig. Jedes Mal, wenn Sie Post-Informationen erhalten, müssen Sie den Status abrufen, oder Sie möchten Posts nach Status filtern. Wenn Sie in einer anderen Tabelle den Status haben, müssen Sie Verknüpfungen erstellen, um diese Informationen abzurufen. Dadurch wird die Leistung beeinträchtigt. Auf jeden Fall sollten Sie den Status in derselben Tabelle haben. Und legen Sie einen Index darauf! Sie können weiterhin Ganzzahlen als Status- oder vielleicht auch Enum-Feld verwenden.

dxvargas
quelle
-2

Die richtige Lösung besteht darin, entweder einen Ereignisspeicher / eine Ereignisquelle mit CQRS oder eine Blockchain zu verwenden. Das Problem beim Erfassen von Ereignissen in einer RDB besteht darin, dass die RDB einen Snapshot eines einzelnen Ereignisses in der Zeit speichert und Dinge wie "Status / Zustände" Sequenzen von Mutationen sind, die sich im Laufe der Zeit entwickeln

LastTribunal
quelle
Wenn Sie meinen Beitrag ablehnen wollen, dann machen Sie einen Fall. Sonst bist du nur ein sanfter Lemming, der nur sehr wenig Spielraum außerhalb der Box hat
LastTribunal