Datenbankdesign für aktualisierbare sequentielle Datensätze


7

Ich arbeite an der Erstellung eines Datenmodells zum Speichern von Daten im Zusammenhang mit der Produktionsverfolgung. Ich arbeite für ein Ingenieurbüro, das Daten für unsere Kunden modelliert und analysiert. Der Prozess besteht aus mehreren Schritten und wird ständig aktualisiert.

Ich versuche, die Prozesse zu modellieren und übergeordnete Prozesse und die sequentielle Reihenfolge der Prozesse einzubeziehen.

Zum Beispiel:

Process Table
---------------------
ProcessID - uniqueidentifier
ProcessName - varchar
ProcessDescription - varchar
...

ProcessOrder Table
---------------------
ProcessID - uniqueidentifier FK - Process
ParentProcessID - uniqueidentifier FK - Process
ProcessOrder - int
...

In der ProcessOrderSpalte in der ProcessOrderTabelle wird einfach eine Zahl gespeichert, die angibt, welchen sequentiellen Schritt im übergeordneten Prozess sie darstellt.

Ein Modellierungsverfahren umfasst beispielsweise die folgenden Schritte: Neues leeres Modell erstellen, Modell benennen, Modellparameter eingeben. Die ProcessTabelle würde aussehen wie:

ProcessID | ProcessName | ProcessDescription
-------------------------------------------------
UUID1     | Modeling    | Create Model of Data
UUID2     | New Model   | create new empty model
UUID3     | Name Model  | name model
UUID4     | Parameters  | enter model parameters

Die ProcessOrderTabelle würde aussehen wie:

ProcessID | ParentProcessID | ProcessOrder
--------------------------------------------------
UUID2     | UUID1           | 1
UUID3     | UUID1           | 2
UUID4     | UUID1           | 3

Das Problem bei diesem Entwurf ist, dass sich bei der Aktualisierung des Workflows die Prozessreihenfolge ändert und ich den ProcessOrderDatensatz für den geänderten Prozess und für alle nachfolgenden Datensätze mit demselben aktualisieren muss ParentProcessID.

Gibt es eine bessere Möglichkeit, diese Art von Daten zu speichern und die Normalisierung aufrechtzuerhalten?


Kleiner Hinweis: Haben Ihre ProcessOrder-Tabellen eine generierte PK (vermutlich eine GUID)? {ProcessID | ProcessOrder} sollte wahrscheinlich ein UK haben, wäre aber angesichts der sich ändernden Werte in ProcessOrder nicht ideal als PK.
Jon of All Trades

Antworten:


0

Ihr Design erscheint mir vernünftig. Während Sie alle nachfolgenden Datensätze aktualisieren müssen, wenn neue Prozesse hinzugefügt oder gelöscht werden, ist dies einfach durchzuführen. Sie geben nur ein Update heraus wie:

UPDATE ProcessOrder
SET ProcessOrder = ProcessOrder+1
WHERE ProcessOrder >= [step# where you want to insert]

und dann einfügen oder löschen.

Die einzige andere Möglichkeit, die ich mir vorstellen kann, besteht darin, das Schema so zu entwerfen, dass die nächste Prozess-ID in der Zeile gespeichert wird. Etwas wie:

ProcessID | ParentProcessID | NextId
--------------------------------------------------
UUID2     | UUID1           | UUID3
UUID3     | UUID1           | UUID4
UUID4     | UUID1           | NULL

Wenn Sie dann einen neuen Schritt einfügen - beispielsweise zwischen UUID3 und UUID4 -, führen Sie eher eine verknüpfte Listenoperation aus, bei der die NextId von UUID3 | UUID1 auf UUID5 aktualisiert wird, und fügen Sie dann einfach die neue UUID5 mit einer NextId von UUID4 ein.

Dies reduziert die UPDATEs in den meisten Fällen auf 1, erschwert jedoch das Abfragen des Prozesses, da Sie jetzt die Liste von oben nach unten durchlaufen müssen, um sie Schritt für Schritt aufzulisten.

Sie müssen entscheiden, welchen Prozess Sie bevorzugen möchten - Einfügen und Aktualisieren oder Abrufen. Wenn Sie das Abrufen bevorzugen (was möglicherweise der Fall ist, wenn Änderungen selten sind und häufig Berichte erstellt werden und die Listen kurz sind), wählen Sie Ihr ursprüngliches Design. Wenn Sie das Einfügen und Aktualisieren bevorzugen (was möglicherweise der Fall ist, wenn ständig Änderungen vorgenommen werden und die Berichterstellung selten ist oder die Listen wirklich sehr lang sind), wählen Sie den Ansatz für verknüpfte Listen.

Ich hoffe das hilft. Interessiert daran, welche anderen Lösungen die Community finden könnte, da ich gerne mein Wissen darüber erweitern würde!


Vielen Dank für Ihre Antwort. Es ist sehr hilfreich. Ich denke, ich werde mich mehr auf die Abfrage konzentrieren als auf das Einfügen oder Aktualisieren. Es klingt also so, als ob ich Ihr erstes Beispiel verwenden sollte. Könnten Sie raten, wie ich die Update-Anweisung in einen Trigger setzen könnte?
Brian

Einfügungen würden Ihren Primärschlüssel verletzen, sodass Sie einen Auslöser anstelle des Einfügens erstellen müssen. In diesem Trigger müssten Sie überprüfen, ob der eingefügte Datensatz die PK verletzt, und ob er dann das Update ausführt, das ich mit dem ProcessOrder aus der INSERTED-Tabelle als Schritt # beschrieben habe. Führen Sie dann das INSERT aus. Zum Löschen müssen Sie einen BEFORE DELETE-Trigger schreiben, der das UPDATE ausführt, das ich mit ProcessOrder aus der DELETED-Tabelle als Schritt # beschrieben habe. Es wären keine Überprüfungen erforderlich. Sie möchten KEINE UPDATE-Trigger haben, da diese ausgelöst werden, wenn Ihr INS / DEL-Trigger ausgelöst wird.
Todd Everett

1

Wenn Sie nur speichern müssen, welcher Schritt Ihres Prozesses nach welchem ​​vorherigen Schritt erfolgt, benötigen Sie lediglich Folgendes:

ProcessID | ParentProcessID | PreviousProcessID

Natürlich benötigen Sie eine FK-Einschränkung, um sicherzustellen, dass (ParentProcessID | PreviousProcessID) auf eine gültige (ParentProcessID | ProcessID) verweist.

Wenn ich Ihre Anforderungen verstanden habe und dieses Design gültig ist, ist es einfach, Schritte in Ihrem Prozess einzufügen, zu entfernen oder zu verschieben. Sie müssen keine Änderungen an Ihren untergeordneten Tabellen weitergeben, da diese auf Ihren Primärschlüssel in (ParentProcessID) verweisen | ProcessID).

HIH


0

Ein paar Fragen zuerst ...

  1. Warum werden Sie eindeutige Bezeichner als Schlüsselspalten verwenden? Ich sehe das oft in Datenbanken und bin mir nie sicher warum. Wenn Sie wirklich einen Datensatz benötigen, der in der gesamten Datenbank oder sogar über mehrere Systeme / Datenbanken hinweg eindeutig ist, ist dies vollkommen in Ordnung. Wenn dies jedoch nicht der Fall ist und der Datensatz nur in der Tabelle eindeutig sein muss, verwenden Sie einen ganzzahligen Wert. Selbst wenn Sie einen BIGINT verwenden müssen, sind Sie besser dran. Ein BIGINT-Typ ist 8 Byte, während ein UNIQUEIDENTIFIER als 16-Byte-Binärzeichenfolge gespeichert ist.
  2. Wie sieht der Workflow auf Anwendungsebene in Bezug auf die Aktualisierung der Prozessreihenfolge aus? Der Grund, den ich frage, ist, dass Sie möglicherweise mehrere UPDATE-Anweisungen vermeiden können, wenn Sie alles im lokalen Speicher speichern können, bis der Workflow abgeschlossen ist. Wenn es sich bei der Front-End-Anwendung beispielsweise um eine ASP.NET-Webanwendung handelt, können Sie alles im Sitzungsstatus speichern, Benutzern den Abschluss des gesamten Workflows ermöglichen und anschließend einen einzelnen Datenbankvorgang ausführen.
  3. Ist es möglich, dass mehrere Benutzer gleichzeitig Komponenten desselben Prozessworkflows bearbeiten? In diesem Fall müssen Sie Überprüfungen durchführen, um sicherzustellen, dass zwei Benutzer sich nicht gegenseitig auf die Zehen treten können.
  4. Was ist mit einer Prozesshistorie für Auditing und Berichterstellung? Wenn Sie Datensätze aktualisieren, verlieren Sie den gesamten Verlauf vollständig. Sie können niemals einen Bericht vorlegen, in dem die verschiedenen Prozessschritte, die Zeit für den Wechsel von einem zum anderen usw. aufgeführt sind.

Drei und vier oben können gelöst werden, indem Datensätze für jede einzelne Änderung eingefügt werden, anstatt Datensätze zu aktualisieren. Dies wird natürlich eine Menge zusätzlicher Daten erzeugen, aber es wird Ihnen auch eine Menge zusätzlicher Einblicke in den Workflow selbst geben und schließlich Informationen bereitstellen, die für Trends, PKIs und andere Business Intelligence verwendet werden können, was uns zum Data Warehousing bringt. Aber das ist ein anderer Beitrag.


0

Der Prozessschritt ist in Ihrem Fall nur dann sinnvoll, wenn eine Prozessversion definiert ist. Man könnte also sagen, dass die Schritte von Prozess 1 in dieser Reihenfolge (a, b, d, c) ausgeführt wurden, als der Prozess in Version 1 war, aber in Version 2 wurde die Schrittausführungsreihenfolge in (a, b, c) geändert. Daher denke ich, dass eine Prozessversion wichtig ist.

Das folgende Diagramm zeigt meinen Vorschlag.

Das Dumme daran ist, dass Sie, wenn Sie die Reihenfolge eines Schritts ändern, alle Schritte erneut in die neue Reihenfolge einfügen müssen, aber in diesem Fall spielt es weder räumlich noch zeitlich eine Rolle.

Geben Sie hier die Bildbeschreibung ein

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.