Wenn Sie zu "benutzerdefinierten Feldern" gelangen, wie sie häufig in Bug - Trackern, Kundenressourcenverwaltung und ähnlichen Geschäftstools zu finden sind, werden sie nicht mit einer Tabelle mit Bajillion - Feldern unterstützt (wenn dies der Fall ist, ist dies wahrscheinlich ein Problem seine eigene).
Stattdessen finden Sie Tabellenentwürfe für Entitätsattributwerte und das zugehörige Verwaltungstool zum Verwalten der gültigen Attribute.
Betrachten Sie die folgende Tabelle:
+ -------------- +
| sache |
| -------------- |
| id |
| Typ |
| desc |
| attr1 |
| attr2 |
| attr3 |
| attr4 |
| attr5 |
+ -------------- +
Dies ist, nachdem Sie einige Attribute hinzugefügt haben. Anstatt so zu attr1
tun, als würde es lesen artist
oder tracks
oder genre
oder welche Attribute das Ding hat. Und statt 5, was wäre, wenn es 50 wäre? Das ist natürlich nicht zu handhaben. Außerdem ist eine Aktualisierung des Modells und eine erneute Bereitstellung der Anwendung erforderlich, um ein neues Feld bearbeiten zu können. Nicht ideal.
Betrachten Sie nun die folgende Tabellenstruktur:
+ -------------- + + --------------- + + ------------- +
| sache | | thing_attr | | attr |
| -------------- | | --------------- | | ------------- |
| id | <--- + | thing_id (fk) | +> | id |
| Typ | | attr_id (fk) | + - + | name |
| desc | | Wert | | |
+ -------------- + + --------------- + + ------------- +
Sie haben Ihr Ding mit seinen Grundgebieten. Sie haben zwei weitere Tische. Eins mit den Attributen. Jedes Feld ist eine Zeile in der attr
Tabelle. Und dann gibt es das thing_attr
mit einem Paar Fremdschlüsseln, die sich auf den thing
Tisch und den attr
Tisch beziehen . Und dies hat dann ein Wertefeld, in dem Sie den Wert des Feldes für diese Entität speichern.
Und jetzt haben Sie eine Struktur, in der die ATTR-Tabelle zur Laufzeit aktualisiert und neue Felder hinzugefügt (oder entfernt) werden können, ohne dass dies erhebliche Auswirkungen auf die Gesamtanwendung hat.
Die Abfragen sind etwas komplexer und die Validierung wird auch komplexer (entweder flippige gespeicherte Prozeduren oder alle Clients). Es ist ein Kompromiss im Design.
Berücksichtigen Sie auch die Situation, in der Sie eines Tages eine Migration durchführen müssen und Sie zur Anwendung zurückkehren und feststellen, dass es jetzt ein halbes Dutzend oder mehr Attribute als das ursprünglich verteilte Schema gibt. Dies führt zu hässlichen Migrationen und Upgrades, bei denen die Entity Attribute Value-Tabelle bei korrekter Verwendung sauberer sein kann. (Nicht immer, kann aber sein.)
Gibt es Nachteile, nur das Schema zur Laufzeit zu ändern? Wenn der Benutzer glaubt, dass eine Sache ein neues Attribut benötigt, fügen Sie der Tabelle einfach dynamisch eine Spalte hinzu?
Wenn Sie mit der entsprechenden Version der nosql-Datenbank arbeiten, können Sie dies wahrscheinlich tun (beachten Sie, dass die entsprechende Version der nosql wahrscheinlich ein Schlüsselwertspeicher ist, also die EAV-Tabelle für die oben beschriebenen relationalen). ohne zu viel Mühe. Es enthält jedoch alle Kompromisse für nosql, die an anderer Stelle ausführlich beschrieben werden.
Wenn Sie stattdessen an einer relationalen Datenbank arbeiten, benötigen Sie das Schema. Das dynamische Hinzufügen der Spalte bedeutet, dass eine Teilmenge der folgenden Dinge zutrifft:
- Sie programmieren Metadatenbanken. Anstatt in der Lage zu sein, diese Spalte mit einem netten ORM sauber diesem Feld zuzuordnen, tun Sie wahrscheinlich Dinge wie
select *
und führen dann einen komplexen Code aus, um herauszufinden, was die Daten tatsächlich sind (siehe Javas ResultSetMetaData ) und diesen dann in einer Karte zu speichern ( oder ein anderer Datentyp - aber keine netten Felder im Code). Dies wirft dann einiges an Typ- und Typosicherheit weg, die Sie mit dem traditionellen Ansatz haben.
- Sie haben den ORM wahrscheinlich aufgegeben. Dies bedeutet, dass Sie Raw-SQL für den gesamten Code schreiben, anstatt das System die Arbeit für Sie erledigen zu lassen.
- Sie haben es aufgegeben, saubere Upgrades durchzuführen. Was passiert, wenn der Kunde ein Feld mit einem Namen hinzufügt, den auch Ihre nächste Version verwendet? Auf der Matchmaking-Site wurde das Upgrade, das ein
hasdate
Feld zum Speichern eines Zeitstempels hinzufügen möchte, bereits wie hasdate
ein Boolescher Wert für ein erfolgreiches Match definiert ... und das Upgrade wird abgebrochen.
- Sie vertrauen darauf, dass der Kunde das System nicht durch ein reserviertes Wort zerstört, das auch Ihre Abfragen zerstört ... irgendwo.
- Sie haben sich an eine Datenbankmarke gebunden. Die DDL verschiedener Datenbanken ist unterschiedlich. Datenbanktypen sind das einfachste Beispiel dafür.
varchar2
vs text
und dergleichen. Ihr Code zum Hinzufügen der Spalte funktioniert unter MySQL, jedoch nicht unter Postgres, Oracle oder SQL Server.
- Haben Sie den Kunden vertrauen auf die Daten tatsächlich fügen gut ? Sicher, der EAV ist alles andere als ideal, aber jetzt haben Sie einige schreckliche undurchsichtige Tabellennamen, die Sie vom Entwickler nicht hinzugefügt haben, mit dem falschen Indextyp (falls vorhanden), ohne dass im Code Einschränkungen hinzugefügt wurden, wo dies erforderlich ist sein und so weiter.
- Sie haben dem Benutzer, der die Anwendung ausführt, Berechtigungen zum Ändern des Schemas erteilt. Little Bobby Drop Tables ist nicht möglich, wenn Sie sich auf SQL und nicht auf DDL beschränken (Sie können dies natürlich auch tun
delete * from students
, aber Sie können die Datenbank nicht auf schlimme Weise durcheinander bringen). Die Anzahl der Probleme, die beim Schemazugriff aufgrund eines Unfalls oder böswilliger Aktivitäten auftreten können, steigt in die Höhe.
Das läuft wirklich darauf hinaus, "es nicht zu tun". Wenn Sie dies wirklich möchten, verwenden Sie ein bekanntes Muster der EAV-Tabellenstruktur oder eine Datenbank, die dieser Struktur vollständig zugeordnet ist. Lassen Sie nicht zu, dass Personen beliebige Felder in einer Tabelle erstellen. Die Kopfschmerzen sind es einfach nicht wert.