2016-05-24 5 views
2

Ich arbeite in einer Datenbank, um Arbeitsaufträge zu steuern, aber ich habe einige Probleme mit dem Entwurf einer Datenbank.Das beste Design für abhängige Tabellen in einer Arbeitsauftragsdatenbank

Ich habe eine Tabelle:

 
TABLE WorkOrder 
- WorkOrderID 
- DateOfRequest 
- Requestor 
- DrawingNumber 
- Quantity 

Aber ich habe keine Ahnung, wie die folgenden Tabellen in einer normalisierten Weise zu erstellen:

Ein Auftrag nur ein Status haben muss: Genehmigt oder Abgelehnt .

  • Approved Aufträge haben ein ApprovedBy Feld, und fallen in eine dieser beiden Szenarien:
    • Lieferung: Wenn ein Auftrag es DeliveredDate enthalten geliefert wird, sollte, ReceivedBy und ReceivedQuantity. Wir benötigen die Menge, weil eine empfangene Menge weniger oder mehr als die angeforderte Menge sein könnte.
    • Storniert: Wenn eine Bestellung abgebrochen wird, sollte sie , CanceledBy und CanceledReason enthalten.
  • Abgelehnt Aufträge haben RejectedBy und RejectedReason Felder nur.

Ich hoffe, dass jemand mir eine Idee mit diesem Brainstorming zu behandeln geben könnte

+0

Angenommen, Sie müssen nicht mehrere Status von Genehmigt, Abgelehnt verfolgen, dann sollten Sie _alle_ dieser Felder in dieselbe Tabelle einfügen. Optional könnten Sie Prüfbedingungen hinzufügen, die sicherstellen, dass Datensätze, die genehmigt sind, RejectedBy und RejectedReason = NULL usw. haben müssen. Die wichtige Frage lautet: Müssen Sie mehrere Zustandsänderungen im Zeitverlauf verfolgen? Der einzige Grund, warum Sie diese in eine andere Tabelle legen, ist, wenn eine bestimmte Arbeitsreihenfolge im Laufe der Zeit viele Änderungen erfahren hat. –

Antwort

0

Ich würde eine Struktur verwenden, die etwa wie folgt aussieht:

 
    TABLE work_orders 
    - id 
    - drawing 
    - quantity 

    TABLE statuses 
    - id 
    - work_order_id (foreign key to work_orders) 
    - by   (covers requested by, approved by, rejected by and canceled by) 
    - date 
    - type  (delivered | canceled | rejected | requested) 

    TABLE receptions 
    - id   (same as the status id, one-to-one) 
    - quantity 

    TABLE cancelations 
    - id   (same as the status id, one-to-one) 
    - reason 

    TABLE rejections 
    - id   (same as the status id, one-to-one) 
    - reason 

Wenn Sie einen Auftrag erstellen, geben Sie Fügen Sie einen Eintrag in Ihrer Tabelle work_orders sowie einen neuen Status des angeforderten Typs hinzu.

Wenn der Auftrag zugestellt wird, fügen Sie einen neuen Status und einen Empfang mit derselben ID hinzu. Mit diesem System können Sie sogar mehrere Teillieferungen abwickeln.

Wenn der Auftrag abgelehnt oder storniert wird, fügen Sie den Status und einen Eintrag in der entsprechenden Tabelle hinzu. Diese Tabellen könnten zusammengeführt werden, aber wenn Sie sich jemals entscheiden, verschiedene Informationen für diese Statusarten zu speichern, werden Sie in Schwierigkeiten geraten, also würde ich sie wahrscheinlich von Anfang an trennen.

Um den aktuellen Status einer Bestellung zu erfahren, fragen Sie einfach die Statustabelle ab, sortieren nach Datum und erhalten den letzten Eintrag. Sie können sogar die gesamte Zeitleiste eines Auftrags anzeigen, indem Sie alle entsprechenden Status abrufen. Außerdem können Sie mit dieser Struktur einen Teil einer Bestellung erhalten und den Rest stornieren.

Ich hoffe, dass alles einen Sinn ergibt. Fühlen Sie sich frei zu fragen, ob Sie wollen, dass ich es ausarbeite.

0

Sie haben zwei Statuswerte, Genehmigt und Abgelehnt. Genehmigt ist weiter unterteilt in zwei Teilstatuswerte, "Geliefert" und "Storniert". Beginnen wir damit, dass wir drei Statuswerte haben, abgelehnt, geliefert und storniert und sehen, wie unser Design funktioniert.

Die WorkOrder-Tabelle wird wie in der Frage gezeigt, daher benötigen wir eine Statustabelle, die den Status dem Arbeitsauftrag zuordnet, alle Daten für alle Statuswerte enthält und einen Hinweis darauf gibt, wo die Daten liegen Der Status kann gefunden werden.

create table Status(
    WOID int primary key, 
    Value char(1) check(Value in ('R', 'D', 'C')), 
    By  int not null, -- who approved, rejected or authorized this status 
    AsOf date not null, -- and when. 
    constraint FK_Status_WorkOrder(WOID) 
     references WordOrder(ID), 
    constraint FK_By_Employee(By) 
     references Employee(ID) 
); 

Zu diesem Zeitpunkt wissen wir dort verwendet, um mehr Tabellen werden Statusdetails (benannt, als eine Vermutung, so etwas wie Rejects, Lieferungen, Brechen) enthalten. Aber wir können kein Feld definieren, das für jede dieser anderen Tabellen ein FK ist, und die Definition von drei solchen Feldern wird sowohl das Design als auch die Aufrechterhaltung der Datenintegrität der laufenden Datenbank erschweren. Zum Glück gibt es einen Weg um ihn herum.

Wir haben die FKs in den drei Detailtabellen, die sich auf die Status-Tabelle beziehen. Aber zuerst müssen wir durch das Hinzufügen einer zusätzlichen Einschränkung der Statustabelle vorbereiten:

create table Status(
    ..., 
    constraint UQ_Status_By_Type unique(WOID, Value) 
); 

Wenn Sie Aufmerksamkeit zahlen sind, können Sie sich fragen, warum wir einen eindeutigen Index für zwei Felder erzeugen würde, von denen einzigartig ganz für sich. Der Grund besteht darin, einen Hook zu definieren, auf den die drei Detailtabellen zugreifen können.

create table Rejects(
    WOID int primary key, 
    Value char(1) check(Value = 'R'), 
    Reason varchar(10), 
    constraint FK_Rejects_Status(WOID, Value) 
     references Status(WOID, Value) 
); 

Die anderen Detailtabellen sind ähnlich definiert.

Lassen Sie uns untersuchen, was wir bisher haben. Das WOID-Feld der Status-Tabelle stellt sicher, dass es für jeden Arbeitsauftrag nicht mehr als einen Status geben kann und dass die Prüfbeschränkung sicherstellt, dass es entweder Abgelehnt, Geliefert oder Abgebrochen sein muss. Wenn ein WO-Status beispielsweise als Abgelehnt definiert ist, muss in der Status-Tabelle ein Eintrag mit einem Wert von "R" gemacht werden. Daher kann nur ein entsprechender Eintrag in der Abweisungstabelle (der nur einen Wert von "R" enthalten kann) für diese WO gemacht werden. Ein Eintrag in der Tabelle Delivered (der nur einen Statuswert von "D" haben kann) würde vom System abgelehnt.

So wird die Datenintegrität beibehalten. Leider ist die Datenintegrität am Ende des Designs zu oft beschlagnahmt. Ich denke, es sollte das primäre Designprinzip sein.

Verfeinerungen sind natürlich möglich. Beispielsweise könnte das Value-Feld der Statustabelle anstelle einer Prüfbeschränkung selbst ein Fremdschlüssel für eine Nachschlagetabelle sein. Das würde es leicht machen, zu einem späteren Zeitpunkt neue Statuswerte hinzuzufügen.