Tak więc, zgodnie z odpowiedzią Mehrdada na pokrewne pytanie , rozumiem, że „właściwa” kolumna tabeli bazy danych nie przechowuje listy. Należy raczej utworzyć inną tabelę, która skutecznie przechowuje elementy tej listy, a następnie połączyć się z nią bezpośrednio lub za pośrednictwem tabeli skrzyżowań. Jednak typ listy, który chcę utworzyć, będzie składał się z unikalnych elementów (w przeciwieństwie do owocu pytania, do którego prowadzi linkprzykład). Co więcej, pozycje na mojej liście są jawnie posortowane - co oznacza, że gdybym przechowywał elementy w innej tabeli, musiałbym je sortować za każdym razem, gdybym miał do nich dostęp. Wreszcie lista jest w zasadzie atomowa, ponieważ za każdym razem, gdy chcę uzyskać dostęp do listy, będę chciał uzyskać dostęp do całej listy, a nie tylko jej części - więc wydaje się głupie, aby wysłać zapytanie do bazy danych, aby zebrać razem fragmenty Lista.
Rozwiązanie AKX (link powyżej) polega na serializacji listy i przechowywaniu jej w kolumnie binarnej. Ale to również wydaje się niewygodne, ponieważ oznacza, że muszę się martwić serializacją i deserializacją.
Czy jest jakieś lepsze rozwiązanie? Jeśli nie to nie ma lepszego rozwiązania, to dlaczego? Wydaje się, że ten problem od czasu do czasu powinien się pojawiać.
... tylko trochę więcej informacji, abyś wiedział, skąd pochodzę. Gdy tylko zacząłem rozumieć SQL i ogólnie bazy danych, zostałem włączony do LINQ to SQL, więc teraz jestem trochę zepsuty, ponieważ spodziewam się poradzić sobie z moim modelem obiektów programowania bez zastanawiania się, jak obiekty są wyszukiwane lub przechowywane w bazie danych.
Dziękuje wszystkim!
Jan
AKTUALIZACJA: Więc w pierwszej lawinie odpowiedzi, które otrzymuję, widzę „możesz przejść na trasę CSV / XML ... ale NIE!”. Więc teraz szukam wyjaśnienia, dlaczego. Wskaż mi kilka dobrych referencji.
Ponadto, aby dać ci lepsze wyobrażenie o tym, co zamierzam: w mojej bazie danych mam tabelę funkcji, która będzie miała listę par (x, y). (Tabela będzie zawierała również inne informacje, które nie mają znaczenia dla naszej dyskusji). Nigdy nie będę potrzebował widzieć części listy par (x, y). Raczej wezmę je wszystkie i narysuję na ekranie. Pozwolę użytkownikowi przeciągać węzły, aby od czasu do czasu zmieniać wartości lub dodawać więcej wartości do wykresu.
Możesz po prostu zapomnieć o SQL i wybrać podejście „NoSQL”. RavenDB , MongoDB i CouchDB skok na myśl jako możliwych rozwiązań. Dzięki podejściu NoSQL nie używasz modelu relacyjnego… nie jesteś nawet ograniczony do schematów.
źródło
Widziałem, jak wiele osób robi to (może to nie być najlepsze podejście, popraw mnie, jeśli się mylę):
Tabela, której używam w przykładzie, jest podana poniżej (tabela zawiera pseudonimy, które nadałeś swoim konkretnym dziewczynom. Każda dziewczyna ma unikalny identyfikator):
Załóżmy, że chcesz przechowywać wiele pseudonimów pod jednym identyfikatorem. Dlatego włączyliśmy
seq_no
pole.Teraz wprowadź te wartości do swojej tabeli:
Jeśli chcesz znaleźć wszystkie imiona, które nadałeś swojej dziewczynie id 1, możesz użyć:
źródło
Prosta odpowiedź: jeśli i tylko wtedy, gdy masz pewność, że lista zawsze będzie używana jako lista, połącz ją na końcu ze znakiem (takim jak „\ 0”), który nie będzie używany w tekst zawsze i przechowuj to. Następnie, gdy go odzyskasz, możesz podzielić przez „\ 0”. Istnieją oczywiście inne sposoby rozwiązania tego problemu, ale zależą one od konkretnego dostawcy bazy danych.
Na przykład możesz przechowywać JSON w bazie danych Postgres. Jeśli Twoja lista jest tekstowa i chcesz po prostu listę bez dalszych kłopotów, to rozsądny kompromis.
Inni odważyli się na sugestie serializacji, ale nie sądzę, aby serializacja była dobrym pomysłem: część fajnej rzeczy w bazach danych polega na tym, że kilka programów napisanych w różnych językach może ze sobą rozmawiać. A programy serializowane przy użyciu formatu Javy nie zrobiłyby tak dobrze, gdyby program Lisp chciał je załadować.
Jeśli chcesz mieć dobry sposób na zrobienie tego typu rzeczy, zwykle dostępne są typy tablicowe lub podobne. Na przykład Postgres oferuje tablicę jako typ i pozwala przechowywać tablicę tekstu, jeśli tego chcesz , a są podobne sztuczki dla MySql i MS SQL używające JSON, a IBM DB2 oferuje również typ tablicy (w ich własną pomocną dokumentację). Nie byłoby to tak powszechne, gdyby nie było takiej potrzeby.
To, co tracisz, idąc tą drogą, to postrzeganie listy jako zbioru rzeczy po kolei. Przynajmniej nominalnie bazy danych traktują pola jako pojedyncze wartości. Ale jeśli to wszystko, czego chcesz, powinieneś to zrobić. To ocena wartości, którą musisz sam dla siebie dokonać.
źródło
Oprócz tego, co powiedzieli wszyscy inni, sugerowałbym, abyś przeanalizował swoje podejście w dłuższej perspektywie niż teraz. Jest obecnie zdarza się, że przedmioty są unikalne. Jest obecnie zdarza się, że uciekają się elementy, które wymagają nowej listy. To jest niemal konieczne, że lista jest obecnie krótka. Mimo że nie mam szczegółowych informacji o domenie, myślenie, że te wymagania mogą się zmienić, nie jest zbyt trudne. Jeśli serializujesz swoją listę, pieczesz w sposób nieelastyczny, który nie jest konieczny w bardziej znormalizowanym projekcie. Przy okazji, to niekoniecznie oznacza pełną relację Many: Many. Możesz mieć tylko jedną tabelę podrzędną z kluczem obcym do rodzica i kolumną znaków dla elementu.
Jeśli nadal chcesz przejść tę drogę serializacji listy, możesz rozważyć przechowywanie listy w formacie XML. Niektóre bazy danych, takie jak SQL Server, mają nawet typ danych XML. Jedynym powodem, dla którego proponuję XML jest to, że prawie z definicji ta lista musi być krótka. Jeśli lista jest długa, serializacja jej ogólnie jest okropnym podejściem. Jeśli wybierzesz trasę CSV, musisz wziąć pod uwagę wartości zawierające ogranicznik, co oznacza, że musisz używać identyfikatorów w cudzysłowie. Zakładając, że listy są krótkie, prawdopodobnie nie będzie miało większego znaczenia, czy użyjesz CSV, czy XML.
źródło
Po prostu zapisałbym go jako CSV, jeśli są to proste wartości, powinno to być wszystko, czego potrzebujesz (XML jest bardzo rozwlekły, a serializacja do / z niego prawdopodobnie byłaby przesada, ale byłaby to również opcja).
Oto dobra odpowiedź, jak wyciągać pliki CSV za pomocą LINQ.
źródło
Jeśli potrzebujesz zapytać o listę, zapisz ją w tabeli.
Jeśli zawsze chcesz mieć listę, możesz przechowywać ją jako rozdzielaną listę w kolumnie. Nawet w tym przypadku, jeśli nie masz BARDZO konkretnych powodów, aby tego nie robić, przechowuj je w tabeli przeglądowej.
źródło
Tylko jedna opcja nie została wymieniona w odpowiedziach. Możesz zdenormalizować swój projekt DB. Potrzebujesz więc dwóch stołów. Jedna tabela zawiera właściwą listę, po jednej pozycji w wierszu, inna tabela zawiera całą listę w jednej kolumnie (np. Rozdzielonej przecinkami).
Oto `` tradycyjny '' projekt DB:
Tutaj jest zdenormalizowana tabela:
Pomysł tutaj - utrzymujesz tabelę Lists za pomocą wyzwalaczy lub kodu aplikacji. Za każdym razem, gdy modyfikujesz zawartość List_Item, odpowiednie wiersze w Listach są aktualizowane automatycznie. Jeśli czytasz głównie listy, może to działać całkiem dobrze. Zalety - możesz czytać listy w jednym oświadczeniu. Wady - aktualizacje wymagają więcej czasu i wysiłku.
źródło
Jeśli naprawdę chciałeś przechowywać go w kolumnie i mieć możliwość wykonywania zapytań, wiele baz danych obsługuje teraz XML. Jeśli nie odpytujesz, możesz zapisać je jako wartości oddzielone przecinkami i przeanalizować je za pomocą funkcji, gdy potrzebujesz ich oddzielonych. Zgadzam się ze wszystkimi, chociaż jeśli chcesz użyć relacyjnej bazy danych, dużą częścią normalizacji jest oddzielenie takich danych. Nie mówię jednak, że wszystkie dane pasują do relacyjnej bazy danych. Zawsze możesz zajrzeć do innych typów baz danych, jeśli wiele danych nie pasuje do modelu.
źródło
Myślę, że w niektórych przypadkach możesz stworzyć FAKE "listę" pozycji w bazie danych, na przykład towar ma kilka zdjęć, aby pokazać jego szczegóły, możesz połączyć wszystkie identyfikatory zdjęć podzielone przecinkami i zapisać ciąg w DB, wtedy wystarczy przeanalizować ciąg, kiedy go potrzebujesz. Pracuję teraz nad stroną internetową i planuję to wykorzystać.
źródło
Bardzo niechętnie wybrałem ścieżkę, którą ostatecznie zdecydowałem się obrać z powodu wielu odpowiedzi. Chociaż dodają więcej zrozumienia do tego, czym jest SQL i jego zasady, postanowiłem zostać wyjętym spod prawa. Wahałem się również, czy opublikować swoje odkrycia, ponieważ dla niektórych ważniejsze jest wyładowanie frustracji komuś, kto łamie zasady, niż zrozumienie, że istnieje bardzo niewiele uniwersalnych prawd.
Przetestowałem to obszernie iw moim konkretnym przypadku było to o wiele bardziej wydajne niż używanie typu tablicowego (hojnie oferowanego przez PostgreSQL) lub przeszukiwanie innej tabeli.
Oto moja odpowiedź: z powodzeniem zaimplementowałem listę w jednym polu w PostgreSQL, wykorzystując ustaloną długość każdego elementu listy. Powiedzmy, że każdy element ma kolor jako wartość szesnastkową ARGB, czyli 8 znaków. Możesz więc utworzyć tablicę maksymalnie 10 elementów, mnożąc przez długość każdego elementu:
W przypadku, gdy długość elementów listy jest różna, zawsze możesz wypełnić dopełnienie \ 0
NB: Oczywiście niekoniecznie jest to najlepsze podejście do liczby szesnastkowej, ponieważ lista liczb całkowitych zajmowałaby mniej miejsca, ale ma to na celu zilustrowanie tej idei tablicy przy użyciu stałej długości przydzielonej do każdego elementu.
Powód, dla którego: 1 / Bardzo wygodne: pobierz element i w podłańcuchu i * n, (i +1) * n. 2 / Brak narzutu zapytań krzyżowych. 3 / Bardziej wydajne i oszczędne po stronie serwera. Lista jest jak mały obiekt blob, który klient będzie musiał podzielić.
Chociaż szanuję ludzi przestrzegających zasad, wiele wyjaśnień jest bardzo teoretycznych i często nie uwzględnia faktu, że w niektórych konkretnych przypadkach, szczególnie gdy dążymy do optymalnych kosztów przy rozwiązaniach o niskim opóźnieniu, niektóre drobne poprawki są mile widziane.
„Nie daj Boże, że narusza jakąś świętą, świętą zasadę języka SQL”: przyjęcie bardziej otwartego i pragmatycznego podejścia przed recytacją reguł jest zawsze właściwą drogą. W przeciwnym razie możesz skończyć jak szczery fanatyk recytujący Trzy Prawa Robotyki, zanim zostaniesz zniszczony przez Skynet
Nie udaję, że to rozwiązanie jest przełomem, ani że jest idealne pod względem czytelności i elastyczności bazy danych, ale z pewnością może dać ci przewagę, jeśli chodzi o opóźnienia.
źródło
Wiele baz danych SQL pozwala, aby tabela zawierała podtabelę jako składnik. Zwykłą metodą jest dopuszczenie, aby domena jednej z kolumn była tabelą. Jest to dodatek do użycia pewnej konwencji, takiej jak CSV, do kodowania podstruktury w sposób nieznany DBMS.
Kiedy Ed Codd opracowywał model relacyjny w latach 1969-1970, konkretnie zdefiniował normalną formę , która uniemożliwiłaby tego rodzaju zagnieżdżanie tabel. Forma normalna została później nazwana First Normal Form. Następnie pokazał, że dla każdej bazy danych istnieje baza danych w pierwszej normalnej formie, która wyraża te same informacje.
Po co się tym przejmować? Cóż, bazy danych w pierwszej normalnej postaci umożliwiają dostęp do wszystkich danych za pomocą klucza. Jeśli podasz nazwę tabeli, wartość klucza do tej tabeli i nazwę kolumny, baza danych będzie zawierała co najwyżej jedną komórkę zawierającą jeden element danych.
Jeśli pozwolisz, aby komórka zawierała listę, tabelę lub jakąkolwiek inną kolekcję, nie możesz teraz zapewnić dostępu za pomocą klucza do elementów podrzędnych, bez całkowitego przeprojektowania koncepcji klucza.
Kluczowy dostęp do wszystkich danych ma fundamentalne znaczenie dla modelu relacyjnego. Bez tej koncepcji model nie jest relacyjny. Odnośnie do tego, dlaczego model relacyjny jest dobrym pomysłem i jakie mogą być ograniczenia tego dobrego pomysłu, należy spojrzeć na 50 lat zgromadzonych doświadczeń z modelem relacyjnym.
źródło
możesz zapisać go jako tekst, który wygląda jak lista i utworzyć funkcję, która może zwrócić dane jako rzeczywistą listę. przykład:
Baza danych:
I funkcja kompilatora list (napisana w Pythonie, ale powinna być łatwa do przetłumaczenia na większość innych języków programowania). TEXT reprezentuje tekst załadowany z tabeli sql. zwraca listę łańcuchów z łańcucha zawierającego listę. jeśli chcesz, aby zwracał ints zamiast łańcuchów, ustaw tryb równy „int”. Podobnie jest z „string”, „bool” czy „float”.
Również tutaj jest funkcja listy do łańcucha na wypadek, gdybyś jej potrzebowała.
źródło