wake-up-neo.com

So speichern Sie eine Liste in einer Spalte einer Datenbanktabelle

Also, per Mehrdads Antwort auf eine verwandte Frage , I verstehe, dass eine "richtige" Datenbanktabellenspalte keine Liste speichert. Sie sollten stattdessen eine andere Tabelle erstellen, die die Elemente dieser Liste effektiv enthält, und dann direkt oder über eine Junction-Tabelle eine Verknüpfung zu dieser Tabelle herstellen. Die Art der Liste, die ich erstellen möchte, setzt sich jedoch aus eindeutigen Elementen zusammen (im Gegensatz zum Beispiel fruit der verknüpften Frage). Außerdem sind die Elemente in meiner Liste explizit sortiert. Wenn ich die Elemente in einer anderen Tabelle gespeichert habe, müsste ich sie jedes Mal sortieren, wenn ich darauf zugreife. Schließlich ist die Liste grundsätzlich unteilbar, da ich jedes Mal, wenn ich auf die Liste zugreifen möchte, auf die gesamte Liste zugreifen möchte und nicht nur auf einen Teil davon. Es ist also albern, eine Datenbankabfrage ausgeben zu müssen, um Teile von zu sammeln Die Liste.

Die Lösung von AKX (siehe oben) besteht darin, die Liste zu serialisieren und in einer binären Spalte zu speichern. Dies scheint jedoch auch unpraktisch zu sein, da ich mich um Serialisierung und Deserialisierung kümmern muss.

Gibt es eine bessere Lösung? Wenn es is keine bessere Lösung gibt, warum dann? Es scheint, dass dieses Problem von Zeit zu Zeit auftreten sollte.

... nur ein paar Infos, um dich wissen zu lassen, woher ich komme. Sobald ich gerade angefangen hatte, SQL und Datenbanken im Allgemeinen zu verstehen, wurde ich auf LINQ to SQL umgestellt, und jetzt bin ich ein wenig verwöhnt, weil ich damit rechne, mit meinem Programmierobjektmodell umzugehen, ohne darüber nachdenken zu müssen, wie die Objekte aussehen abgefragt oder in der Datenbank gespeichert werden.

Vielen Dank an alle!

John

UPDATE: Bei den ersten Antworten sehe ich, dass Sie die CSV/XML-Route einschlagen können, aber NICHT! Jetzt suche ich nach Erklärungen, warum. Zeig mir ein paar gute Referenzen.

Außerdem, um Ihnen eine bessere Vorstellung davon zu geben, was ich vorhabe: In meiner Datenbank habe ich eine Funktionstabelle, die eine Liste von (x, y) Paaren enthält. (Die Tabelle wird auch andere Informationen enthalten, die für unsere Diskussion keine Bedeutung haben.) Ich werde niemals einen Teil der Liste von (x, y) Paaren sehen müssen. Vielmehr nehme ich sie alle und zeichne sie auf dem Bildschirm. Ich erlaube dem Benutzer, die Knoten zu ziehen, um die Werte gelegentlich zu ändern oder dem Plot weitere Werte hinzuzufügen.

96
JnBrymn

Nein, es gibt keine "bessere" Möglichkeit, eine Abfolge von Elementen in einer einzelnen Spalte zu speichern. Relationale Datenbanken sind darauf ausgelegt,specificeinen Wert pro Zeilen-/Spaltenkombination zu speichern. Um mehr als einen Wert zu speichern, müssen SiemustIhre Liste in einen einzigen Wert zum Speichern serialisieren und dann beim Abrufen deserialisieren. Es gibt keine andere Möglichkeit, das zu tun, wovon Sie sprechen (denn es handelt sich um eineschlechte Idee, die im Allgemeinen niemals gemacht werden sollte).

Ich verstehe, dass Sie es für dumm halten, eine weitere Tabelle zum Speichern dieser Liste zu erstellen, aber genau das tun relationale Datenbanken. Sie kämpfen einen harten Kampf und verletzen ohne guten Grund eines der grundlegendsten Prinzipien des relationalen Datenbankdesigns. Da Sie angeben, dass Sie nur SQL lernen, empfehle ich Ihnen nachdrücklich , diese Idee zu vermeiden und sich an die Praktiken zu halten, die Ihnen von erfahrenerem SQL empfohlen werden Entwickler.

Das Prinzip, gegen das Sie verstoßen, heißtfirst normal form. Dies ist der erste Schritt bei der Datenbanknormalisierung.

Bei der Datenbanknormalisierung wird die Datenbank auf der Grundlage der Datenalsdefiniert, sodass Sie sinnvolle, konsistente Abfragen erstellen und bearbeiten können in der Lage, es leicht zu pflegen. Die Normalisierung soll logische Inkonsistenzen und Beschädigungen Ihrer Daten begrenzen, und es gibt viele Ebenen. Der Wikipedia-Artikel über Datenbanknormalisierung ist eigentlich ziemlich gut.

Grundsätzlich besagt die erste Regel (oder Form) der Normalisierung, dass Ihre Tabelle eine Beziehung darstellen muss. Das bedeutet, dass:

  • Sie müssen in der Lage sein, eine Zeile von jeder anderen Zeile zu unterscheiden (mit anderen Worten, Ihre Tabelle muss etwas enthalten, dasals Primärschlüssel dienen kann. Dies bedeutet auch, dass keine Zeile vorhanden ist sollte dupliziert werden.
  • Jede Reihenfolge der Daten muss durch die Daten definiert werden, nicht durch die physische Reihenfolge der Zeilen (SQL basiert auf der Idee einer Menge, was bedeutet, dassonlyordering Sie sollten sich auf das verlassen, was Sie explizit in Ihrer Abfrage definieren.)
  • Jeder Zeilen-/Spaltenschnittpunkt darf einenund nur einenWert enthalten

Der letzte Punkt ist offensichtlich der hervorstechende Punkt hier. SQL wurde entwickelt, um Ihre Sets für Sie zu speichern, ohne Ihnen einen "Eimer" zur Verfügung zu stellen, in dem Sie ein Set selbst speichern können. Ja, das ist möglich. Nein, die Welt wird nicht untergehen. Sie haben sich jedoch bereits in das Verständnis von SQL und den damit verbundenen Best Practices verkrüppelt, indem Sie sofort in die Verwendung eines ORM eingestiegen sind. LINQ to SQL ist fantastisch, genau wie Grafikrechner. In der gleichen Weise sollten sie jedochnotals Ersatz dafür verwendet werden, zu wissen, wie die von ihnen angewendeten Prozesse tatsächlich funktionieren.

Ihre Liste ist jetzt möglicherweise vollständig "atomar", und das ändert sich möglicherweise nicht für dieses Projekt. Sie werden sich jedoch angewöhnen, ähnliche Dinge in anderen Projekten zu tun, und Sie werden irgendwann (wahrscheinlich schnell) auf ein Szenario stoßen, in dem Sie jetzt Ihre Quick-n-Easy-Liste in einer Spalte anpassen Ansatz, wo es völlig unangemessen ist. Das Erstellen der richtigen Tabelle für das, was Sie speichern möchten, erfordert nicht viel zusätzlichen Aufwand, und Sie werden von anderen SQL-Entwicklern nicht verspottet, wenn sie Ihren Datenbankentwurf sehen. Außerdem wird LINQ to SQL Ihre Beziehung sehen und Ihnen die richtige objektorientierte Schnittstelle zu Ihrer Liste gebenautomatic. Warum würden Sie die Bequemlichkeit, die Ihnen der ORM bietet, aufgeben, damit Sie eine nicht standardmäßige und schlecht beratene Datenbankhackerei durchführen können?

158
Adam Robinson

Sie können SQL einfach alle zusammen vergessen und mit einem "NoSQL" -Ansatz gehen. RavenDB , MongoDB und CouchDB als mögliche Lösungen in den Sinn kommen. Bei einem NoSQL-Ansatz verwenden Sie nicht das relationale Modell. Sie sind nicht einmal an Schemata gebunden.

13
jaltiere

Was ich viele Leute gesehen habe, ist Folgendes (es ist möglicherweise nicht der beste Ansatz, korrigiere mich, wenn ich falsch liege):

Die Tabelle, die ich in dem Beispiel verwende, ist unten angegeben (die Tabelle enthält Spitznamen, die Sie Ihren bestimmten Freundinnen gegeben haben. Jede Freundin hat eine eindeutige ID):

nicknames(id,seq_no,names)

Angenommen, Sie möchten viele Kurznamen unter einer ID speichern. Aus diesem Grund haben wir ein seq_no Feld.

Füllen Sie nun diese Werte in Ihre Tabelle:

(1,1,'sweetheart'), (1,2,'pumpkin'), (2,1,'cutie'), (2,2,'cherry pie')

Wenn Sie alle Namen finden möchten, die Sie Ihrer Freundin mit der ID 1 gegeben haben, können Sie Folgendes verwenden:

select names from nicknames where id = 1;
8
user5157248

Zusätzlich zu dem, was alle anderen gesagt haben, würde ich vorschlagen, dass Sie Ihren Ansatz länger analysieren als jetzt. Es ist derzeit der Fall, dass Artikel einzigartig sind. Es ist derzeit der Fall, dass das Umsortieren der Elemente eine neue Liste erfordern würde. Es ist fast erforderlich, dass die Liste derzeit kurz ist. Auch wenn ich die Domain-Details nicht kenne, ist es nicht schwer zu glauben, dass sich diese Anforderungen ändern könnten. Wenn Sie Ihre Liste serialisieren, backen Sie in einer Inflexibilität, die in einem normalisierten Design nicht erforderlich ist. Übrigens, das bedeutet nicht unbedingt eine vollständige Many: Many-Beziehung. Sie könnten nur eine einzige untergeordnete Tabelle mit einem Fremdschlüssel für das übergeordnete Element und einer Zeichenspalte für das Element haben.

Wenn Sie die Liste dennoch serialisieren möchten, sollten Sie die Liste in XML speichern. Einige Datenbanken wie SQL Server haben sogar einen XML-Datentyp. Der einzige Grund, warum ich XML vorschlagen würde, ist, dass diese Liste fast per Definition kurz sein muss. Wenn die Liste lang ist, ist das Serialisieren im Allgemeinen ein schrecklicher Ansatz. Wenn Sie die CSV-Route wählen, müssen Sie die Werte berücksichtigen, die das Trennzeichen enthalten. Dies bedeutet, dass Sie gezwungen sind, Bezeichner in Anführungszeichen zu verwenden. Wenn Sie davon ausgehen, dass die Listen kurz sind, wird es wahrscheinlich keinen großen Unterschied machen, ob Sie CSV oder XML verwenden.

3
Thomas

Einfache Antwort: Wenn und nur wenn Sie sicher sind, dass die Liste immer als Liste verwendet wird, fügen Sie die Liste an Ihrem Ende mit einem Zeichen (z. B. '\ 0') zusammen, das in der Liste nicht verwendet wird Text überhaupt und speichern das. Wenn Sie es dann abrufen, können Sie durch '\ 0' teilen. Es gibt natürlich auch andere Möglichkeiten, diese Dinge zu erledigen, aber diese hängen von Ihrem jeweiligen Datenbankanbieter ab.

Beispielsweise können Sie JSON in einer Postgres-Datenbank speichern. Wenn es sich bei Ihrer Liste um Text handelt und Sie die Liste nur ohne weiteren Aufwand anzeigen möchten, ist dies ein vernünftiger Kompromiss.

Andere haben Vorschläge zur Serialisierung gemacht, aber ich halte Serialisierung nicht wirklich für eine gute Idee: Das Schöne an Datenbanken ist, dass mehrere in verschiedenen Sprachen geschriebene Programme miteinander kommunizieren können. Und Programme, die im Java-Format serialisiert wurden, würden nicht allzu gut funktionieren, wenn ein LISP-Programm sie laden wollte.

Wenn Sie einen guten Weg suchen, um so etwas zu tun, stehen normalerweise Array- oder ähnliche Typen zur Verfügung. Postgres zum Beispiel bietet Array als Typ an und lässt Sie ein Array von Text speichern, wenn Sie dies möchten , und es gibt ähnliche Tricks für MySql und MS SQL mit JSON und IBMs DB2 bieten auch einen Array-Typ an (in ihrer eigenen hilfreichen Dokumentation) . Dies wäre nicht so üblich, wenn dies nicht erforderlich wäre.

Was Sie verlieren, wenn Sie diesen Weg gehen, ist der Begriff der Liste als ein Bündel von Dingen in Folge. Zumindest nominal behandeln Datenbanken Felder als einzelne Werte. Aber wenn das alles ist, was Sie wollen, sollten Sie es versuchen. Es ist ein Werturteil, das Sie für sich selbst treffen müssen.

2
Haakon Løtveit

Wenn Sie die Liste abfragen müssen, speichern Sie sie in einer Tabelle.

Wenn Sie die Liste immer möchten, können Sie sie als begrenzte Liste in einer Spalte speichern. Auch in diesem Fall sollten Sie es in einer Nachschlagetabelle speichern, es sei denn, Sie haben SEHR bestimmte Gründe, dies nicht zu tun.

2
hometoast

Nur eine Option wird in den Antworten nicht erwähnt. Sie können Ihr DB-Design de-normalisieren. Sie brauchen also zwei Tische. Eine Tabelle enthält die richtige Liste, ein Element pro Zeile, eine andere Tabelle enthält die gesamte Liste in einer Spalte (z. B. durch Kommas getrennt).

Hier ist es "traditionelles" DB-Design:

List(ListID, ListName) 
Item(ItemID,ItemName) 
List_Item(ListID, ItemID, SortOrder)

Hier ist es de-normalisierte Tabelle:

Lists(ListID, ListContent)

Die Idee hier - Sie pflegen die Lists-Tabelle mithilfe von Triggern oder Anwendungscode. Jedes Mal, wenn Sie den Inhalt von List_Item ändern, werden die entsprechenden Zeilen in Listen automatisch aktualisiert. Wenn Sie meistens Listen lesen, könnte es ganz gut funktionieren. Vorteile - Sie können Listen in einer Anweisung lesen. Nachteile - Updates erfordern mehr Zeit und Mühe.

1
Alsin

Ich würde es einfach als CSV speichern, wenn es einfache Werte sind, dann sollte es alles sein, was Sie brauchen (XML ist sehr ausführlich und Serialisierung von/nach es wäre wahrscheinlich übertrieben, aber das wäre auch eine Option).

Hier ist ein gute Antwort , wie CSVs mit LINQ abgerufen werden können.

1
David Neale

Ich denke, in bestimmten Fällen können Sie eine FAKE "Liste" von Artikeln in der Datenbank erstellen, zum Beispiel hat die Ware ein paar Bilder, um ihre Details anzuzeigen, Sie können alle IDs von Bildern, die durch Komma getrennt sind, verketten und die Zeichenfolge darin speichern die DB, dann müssen Sie nur die Zeichenfolge analysieren, wenn Sie es brauchen. Ich arbeite gerade an einer Website und habe vor, sie auf diese Weise zu nutzen.

0
Nen

Wenn Sie es wirklich in einer Spalte speichern und abfragen möchten, unterstützen viele Datenbanken jetzt XML. Wenn Sie nicht fragen, können Sie sie als durch Kommas getrennte Werte speichern und mit einer Funktion auswerten, wenn Sie sie getrennt benötigen. Ich bin mit allen anderen einverstanden, aber wenn Sie eine relationale Datenbank verwenden möchten, besteht ein großer Teil der Normalisierung darin, Daten wie diese zu trennen. Ich sage aber nicht, dass alle Daten in eine relationale Datenbank passen. Sie können jederzeit nach anderen Datenbanktypen suchen, wenn viele Ihrer Daten nicht zum Modell passen.

0
David Daniel