it-swarm.com.de

Verwenden einer Single Row-Konfigurationstabelle in der SQL Server-Datenbank. Schlechte Idee?

Bei der Entwicklung einer Einkaufswagenanwendung habe ich festgestellt, dass ich Einstellungen und Konfigurationen basierend auf den Präferenzen und Anforderungen des Administrators speichern musste. Diese Informationen können aus Unternehmensinformationen, Versandkonto-IDs, Paypal-API-Schlüsseln, Benachrichtigungseinstellungen usw. bestehen.

Es erscheint äußerst unangebracht, eine Tabelle zum Speichern einer einzelnen Zeile in einem relationalen Datenbanksystem zu erstellen.

Wie speichern Sie diese Informationen am besten?

Hinweis: Mein DBMS ist SQL Server 2008 und die Programmierschicht ist mit ASP.NET (in C #) implementiert.

134
David Murdoch

Ich habe dies in der Vergangenheit auf zwei Arten getan - eine einzelne Zeilentabelle und eine Schlüssel/Wert-Paartabelle - und es gibt für jeden Ansatz positive und negative Aspekte.

Einzelne Reihe

  • positiv: die Werte werden im richtigen Typ gespeichert
  • positiv: es ist einfacher, mit dem Code umzugehen (aufgrund des oben genannten)
  • positiv: Standardwerte können jeder Einstellung einzeln zugewiesen werden
  • negativ: Eine Schemaänderung ist erforderlich, um eine neue Einstellung hinzuzufügen
  • negativ: Die Tabelle kann sehr umfangreich werden, wenn viele Einstellungen vorgenommen werden

Schlüssel/Wert-Paar

  • positiv: das Hinzufügen neuer Einstellungen erfordert keine Schemaänderung
  • positiv: Das Tabellenschema ist schmal und es werden zusätzliche Zeilen für neue Einstellungen verwendet
  • negativ: Jede Einstellung hat den gleichen Standardwert (null/leer?)
  • negativ: alles muss als strings gespeichert werden (dh. nvarchar)
  • negativ: Wenn Sie mit den Einstellungen im Code umgehen, müssen Sie wissen, um welchen Typ es sich bei einer Einstellung handelt 

Die einreihige Option ist bei weitem die einfachste. Dies liegt daran, dass Sie jede Einstellung in ihrem korrekten Typ in der Datenbank speichern können und nicht die Einstellungen und die Suchschlüssel im Code speichern müssen.

Eine Sache, die mich mit diesem Ansatz beschäftigte, war, mehrere Zeilen in der "speziellen" Einzelzeilen-Einstellungstabelle zu haben. Ich habe dies durch (in SQL Server) überwunden:

  • hinzufügen einer neuen Bit-Spalte mit einem Standardwert von 0
  • erstellen einer Prüfbedingung, um sicherzustellen, dass diese Spalte den Wert 0 hat
  • erstellen einer eindeutigen Einschränkung für die Bit-Spalte

Das bedeutet, dass nur eine Zeile in der Tabelle vorhanden sein kann, da die Bit-Spalte den Wert 0 haben muss. Aufgrund der eindeutigen Einschränkung kann jedoch nur eine Zeile mit diesem Wert vorhanden sein.

173
adrianbanks

Sie sollten (mindestens) eine Tabelle mit einer Spalte für den Informationstyp und den Informationswert erstellen. Auf diese Weise müssen Sie nicht jedes Mal neue Spalten erstellen, wenn neue Informationen hinzugefügt werden.

10
Otávio Décio

Eine einzelne Reihe wird gut funktionieren; es wird sogar starke Typen geben:

show_borders    bit
admin_name      varchar(50)
max_users       int

Ein Nachteil besteht darin, dass zum Hinzufügen einer neuen Einstellung eine Schemaänderung (alter table) erforderlich ist. Eine Alternative ist die Normalisierung, bei der Sie eine Tabelle wie:

pref_name       varchar(50) primary key
pref_value      varchar(50) 

Dies hat schwache Typen (alles ist ein Varchar), aber das Hinzufügen einer neuen Einstellung besteht einfach darin, eine Zeile hinzuzufügen. Dies ist nur mit dem Schreibzugriff auf Datenbanken möglich.

6
Andomar

Ich persönlich würde es in einer einzigen Zeile speichern, wenn es funktioniert. Overkill, um es in einer SQL-Tabelle zu speichern? wahrscheinlich, aber es ist kein wirklicher Schaden.

4
E.J. Brennan

Wie Sie sich schon gedacht haben und mit Ausnahme der einfachsten Situationen hat das Platzieren aller Konfigurationsparameter in einer einzelnen Reihe viele Nachteile. Das ist eine schlechte Idee ...

Eine bequeme Methode zum Speichern von Konfigurations- und/oder Benutzereinstellungen ist in XML. Viele DBMS unterstützen den XML-Datentyp. Mit der XML-Syntax können Sie die "Sprache" und die Struktur zur Beschreibung der Konfiguration im Verlauf dieser Konfiguration verwenden. Ein Vorteil von XML ist die implizite Unterstützung der hierarchischen Struktur. So können beispielsweise kleine Listen von Konfigurationsparametern gespeichert werden, ohne dass diese mit einem nummerierten Suffix benannt werden müssen. Ein möglicher Nachteil des XML-Formats besteht darin, dass das Suchen und das Ändern dieser Daten im Allgemeinen nicht so einfach ist wie andere Ansätze (nichts kompliziertes, aber nicht so einfach/natürlich).

Wenn Sie näher am relationalen Modell bleiben möchten, ist das Entity-Attribute-Value-Modell wahrscheinlich das, was Sie brauchen, wobei die einzelnen Werte in einer Tabelle gespeichert werden, die normalerweise wie folgt aussieht:

EntityId     (foreign key to the "owner" of this attribute)
AttributeId  (foreign key to the "metadata" table where the attribute is defined)
StringValue  (it is often convenient to have different columns of different types
IntValue      allowing to store the various attributes in a format that befits 
              them)

Dabei ist die AttributeId ein Fremdschlüssel für eine Tabelle, in der jedes mögliche Attribut (in Ihrem Fall "Konfigurationsparameter") definiert ist, beispielsweise

AttributeId  (Primary Key)
Name
AttributeType     (some code  S = string, I = Int etc.)
Required          (some boolean indicating that this is required)
Some_other_fields   (for example to define in which order these attributes get displayed etc...)

Schließlich können Sie mit der EntityId eine Entität identifizieren, die diese verschiedenen Attribute "besitzt". In Ihrem Fall kann es sich um eine UserId handeln oder auch nur implizit, wenn Sie nur eine Konfiguration verwalten müssen.

Abgesehen davon, dass die Liste der möglichen Konfigurationsparameter mit der Entwicklung der Anwendung vergrößert werden kann, platziert das EAV-Modell die "Metadaten", dh die Daten, die das Attribut selbst betreffen, in Datentabellen und vermeiden so die harte Kodierung der üblicherweise verwendeten Spaltennamen wenn die Konfigurationsparameter in einer einzigen Zeile gespeichert werden.

3
mjv

Sie müssen Ihr Schema sicherlich nicht ändern, wenn Sie einen neuen Konfigurationsparameter in der normalisierten Methode hinzufügen, aber wahrscheinlich ändern Sie Ihren Code trotzdem, um den neuen Wert zu verarbeiten. 

Das Hinzufügen einer "Alterungstabelle" zu Ihrer Bereitstellung ist aufgrund der Einfachheit und der Typsicherheit des einreihigen Ansatzes kein so großer Kompromiss. 

3
Dave Mikesell

Ein Schlüssel/Wert-Paar ähnelt einer .Net App.Config, in der Konfigurationseinstellungen gespeichert werden können.

Wenn Sie also den Wert abrufen möchten, können Sie Folgendes tun:

SELECT value FROM configurationTable
WHERE ApplicationGroup = 'myappgroup'
AND keyDescription = 'myKey';
2
rizalp1

Ein üblicher Weg, dies zu tun, besteht darin, dass eine "Eigenschaften" -Tabelle mit einer Eigenschaftsdatei identisch ist. Hier können Sie alle Ihre App-Konstanten speichern oder nicht so konstante Dinge, die Sie gerade benötigen.

Sie können die Informationen dann aus dieser Tabelle holen, wenn Sie sie benötigen. Wenn Sie feststellen, dass Sie andere Einstellungen zum Speichern haben, können Sie sie ebenfalls hinzufügen. Hier ein Beispiel:

property_entry_table

[id, scope, refId, propertyName, propertyValue, propertyType] 
1, 0, 1, "COMPANY_INFO", "Acme Tools", "ADMIN"  
2, 0, 1, "SHIPPING_ID", "12333484", "ADMIN"  
3, 0, 1, "Paypal_KEY", "2143123412341", "ADMIN"   
4, 0, 1, "Paypal_KEY", "123412341234123", "ADMIN"  
5, 0, 1, "NOTIF_PREF", "ON", "ADMIN"  
6, 0, 2, "NOTIF_PREF", "OFF", "ADMIN"   

Auf diese Weise können Sie die Daten, die Sie haben, und die Daten, die Sie im nächsten Jahr haben werden und noch nicht wissen, speichern :).

In diesem Beispiel können Sie Ihren Gültigkeitsbereich und Ihre RefId für beliebige Zwecke im Backend verwenden. Wenn also propertyType "ADMIN" einen Gültigkeitsbereich von 0, Referenz 2 hat, wissen Sie, welche Einstellung es ist.

Die Art des Eigentums wird angezeigt, wenn Sie eines Tages auch Nicht-Admin-Informationen hier speichern müssen.

Beachten Sie, dass Sie keine Einkaufswagen-Daten auf diese Weise speichern oder danach suchen sollten. Wenn jedoch die Daten sind System spezifisch, dann können Sie diese Methode sicherlich verwenden.

Zum Beispiel: Wenn Sie Ihre speichern möchten DATABASE_VERSIONSie würden einen Tisch wie diesen verwenden. Auf diese Weise können Sie beim Aktualisieren der App in der Eigenschaftentabelle nachsehen, welche Version Ihrer Software der Client hat.

Der Punkt ist, dass Sie dies nicht für Dinge verwenden möchten, die den Einkaufswagen betreffen. Behalten Sie Ihre Geschäftslogik in gut definierten relationalen Tabellen. Die Eigenschaftstabelle dient nur zur Systeminformation.

1
Stephano

Habe eine Schlüsselspalte als Varchar und eine Wertespalte als JSON. 1 ist numerisch, wohingegen "1" eine Zeichenfolge ist. true und false sind beide boolean. Sie können auch Objekte haben.

0
kzh

Sie können das Schlüssel/Wert-Paar ohne Konvertierungen durchführen, indem Sie für jeden Haupttyp eine Spalte und eine Spalte hinzufügen, in der Sie angeben, in welcher Spalte sich die Daten befinden.

Ihr Tisch würde also ungefähr so ​​aussehen:

id, column_num, property_name, intValue, floatValue, charValue, dateValue
1, 1, weeks, 51, , ,
2, 2, pi, , 3.14159, , 
3, 4, FiscYearEnd, , , , 1/31/2015
4, 3, CompanyName, , , ACME, 

Es benötigt etwas mehr Platz, aber höchstens einige Dutzend Attribute. Sie können eine case-Anweisung aus dem Wert von column_num verwenden, um das rechte Feld zu ziehen/zu verknüpfen.

0
spintool

Ich bin nicht sicher, ob eine einzelne Zeile die beste Implementierung für die Konfiguration ist. Es ist möglicherweise besser, pro Konfigurationselement eine Zeile mit zwei Spalten (configName, configValue) zu haben, obwohl dies alle Werte in Strings und zurück umwandeln muss.

Trotzdem schadet es nicht, eine einzige Zeile für die globale Konfiguration zu verwenden. Die anderen Optionen zum Speichern im DB (globale Variablen) sind schlechter. Sie können dies steuern, indem Sie Ihre erste Konfigurationszeile einfügen und Einfügungen in der Tabelle deaktivieren, um mehrere Zeilen zu verhindern.

0
sidereal

Tut mir leid, dass ich später komme. Aber was ich mache, ist einfach und effektiv. Ich erstelle einfach eine Tabelle mit drei () Spalten:

ID - int (11)

name - Varchar (64)

wert - Text

Was ich vor dem Erstellen einer neuen Konfigurationsspalte, dem Aktualisieren oder Lesen mache, ist das Serialisieren des "Werts"! Auf diese Weise bin ich mir des Typs sicher (naja, PHP ist :))

Zum Beispiel:

b: 0; ist fürBOOLEAN (false)

b: 1; ist fürBOOLEAN (true)

i: 1988; ist fürINT

s: 5: "Kader"; steht für einSTRING mit 5 Zeichen

Ich hoffe das hilft :)

0
Kader Bouyakoub