Como armazenar uma lista em uma coluna de uma tabela de banco de dados

Então, por a resposta do Mehrdad a uma pergunta relacionada, EU Obter que uma coluna de tabela de bases de dados" próprias " não armazena uma lista. Em vez disso, você deve criar outra tabela que efetivamente mantém os elementos da referida lista e, em seguida, ligar-se a ela diretamente ou através de uma tabela de junção. No entanto, o tipo de lista que eu quero criar será composto por itens únicos (ao contrário do exemplo da pergunta ligada fruit). Além disso, os itens da minha lista estão explicitamente ordenados-que significa que se guardasse os elementos noutra mesa, teria de os classificar sempre que os acedesse. Finalmente, a lista é basicamente atômica em que sempre que Eu desejo acessar a lista, Eu quero acessar a lista inteira em vez de apenas um pedaço dela - então parece tolo ter que emitir uma consulta de banco de dados para reunir pedaços da lista.

a solução do AKX (ligada acima) é serializar a lista e armazená-la numa coluna binária. Mas isso também parece inconveniente porque significa que tenho de me preocupar com a serialização e a deseralização.

Há alguma solução melhor? Se não existe uma solução melhor, então porquê? Parece que este problema deve surgir de vez em quando.

... só um pouco mais de informação para te dizer de onde venho. Assim que eu tinha acabado de começar a entender SQL e bases de dados em geral, eu estava ligado ao LINQ para SQL, e então agora eu estou um pouco mimado, porque eu espero lidar com o meu modelo de objeto de programação sem ter que pensar sobre como os objetos são pesquisados ou armazenados na base de dados.

Obrigado A Todos!

John

Atualização: assim, na primeira onda de respostas que estou recebendo, eu vejo "você pode ir pela rota CSV/XML... mas não!". Agora estou à procura de explicações sobre o porquê. Aponta-me algumas boas referências.

também, para lhe dar uma ideia melhor do que estou a fazer: na minha base de dados tenho uma tabela de funções que terá uma lista de pares (x,y). (O quadro terá também outras informação que não é relevante para a nossa discussão.) Eu nunca precisarei ver parte da lista de pares (x,y). Em vez disso, vou pegar em todos eles e colocá-los no ecrã. Eu vou permitir que o usuário arraste os nós ao redor para mudar os valores ocasionalmente ou adicionar mais valores para o gráfico.

Author: Community, 2010-06-18

10 answers

Não, Não há uma maneira "melhor" de armazenar uma sequência de itens numa única coluna. As bases de dados relacionais foram concebidas especificamente para armazenar um valor por combinação linha/coluna. A fim de armazenar mais de um valor, você deve serializar a sua lista em um único valor para o armazenamento, em seguida, desertificá-lo após a recuperação. Não há outra maneira de fazer o que você está falando (porque o que você está falando é uma idéia ruim que deve, em geral, nunca ser feito em . Eu entendo que você pense que é tolice criar outra tabela para armazenar essa lista, mas isso é exatamente o que as bases de dados relacionais fazem. Está a lutar uma batalha difícil e a violar um dos princípios mais básicos da criação de bases de dados relacionais sem uma boa razão. Uma vez que afirma que está apenas a aprender SQL, eu aconselhá-lo-ia fortemente a evitar esta ideia e a seguir as práticas recomendadas por programadores SQL mais experientes. O princípio você está violando é chamado de primeira forma normal , que é o primeiro passo na normalização de banco de dados.

Correndo o risco de simplificar demasiado as coisas, a normalização da base de dados é o processo de definir a sua base de dados com base no que os dados são, para que possa escrever consultas sensatas e consistentes contra ela e ser capaz de mantê-la facilmente. A normalização é projetada para limitar inconsistências lógicas e corrupção em seus dados, e há um monte de níveis para ele. taxa o artigo sobre a normalização da base de Dados é muito bom.

Basicamente, a primeira regra (ou forma) de normalização afirma que a sua tabela deve representar uma relação. Isto significa que:

  • você deve ser capaz de diferenciar uma linha de qualquer outra linha (em outras palavras, a sua tabela deve ter algo que Pode servir como uma chave primária. Isto também significa que nenhuma linha deve ser duplicada.
  • qualquer ordenação dos dados deve ser definida pelos dados, não por a ordenação física das linhas (SQL é baseada na idéia de um conjunto, o que significa que a Somente ordenando que você deve confiar é o que você define explicitamente em sua consulta)
  • cada intersecção linha / coluna deve conter um e apenas um Valor
O último ponto é obviamente o ponto mais saliente. SQL é projetado para armazenar seus conjuntos para você, não para fornecer-lhe um "balde" para você armazenar um conjunto você mesmo. Sim, é possível. Não, o o mundo não vai acabar. Você, no entanto, já se aleijou na compreensão do SQL e das melhores práticas que vão junto com ele, saltando imediatamente para o uso de uma ORM. LINQ para SQL é fantástico, assim como calculadoras de gráficos são. Na mesma linha, porém, eles não devem ser usados como um substituto para saber como os processos que empregam realmente funcionam.

A tua lista pode ser completamente "atómica" agora, e isso pode não mudar para este projecto. Mas você vai, no entanto, entrar no hábito de fazer coisas semelhantes em outros projetos, e você eventualmente (provavelmente rapidamente) vai encontrar um cenário onde você agora está encaixando sua abordagem rápida-n-Fácil de lista-em-uma-coluna, onde é totalmente inapropriado. Não há muito trabalho adicional na criação da tabela correta para o que você está tentando armazenar, e você não será ridicularizado por outros desenvolvedores SQL quando eles vêem o seu projeto de banco de dados. Além disso, o LINQ para o SQL vai ver a sua relação e dar-lhe a interface adequada orientada a objectos para a sua lista automaticamente. Por que você desistiria da conveniência oferecida pelo ORM para que você possa executar hackery de banco de dados não-padrão e mal aconselhado?

 128
Author: Adam Robinson, 2010-06-18 14:52:36
Podes esquecer o SQL todos juntos e fazer uma abordagem" NoSQL". RavenDB, MongoDB e CouchDB jump to mind as possible solutions. Com uma abordagem NoSQL, você não está usando o modelo relacional..nem sequer estás limitado a esquemas.
 8
Author: jaltiere, 2010-06-18 14:34:44

O que eu vi muitas pessoas fazerem é isto (pode não ser a melhor abordagem, corrija-me se estiver errado):

A tabela que estou a usar no exemplo é dada abaixo(a tabela inclui alcunhas que você deu às suas namoradas específicas. Cada namorada tem um id único):

nicknames(id,seq_no,names)
Suponho que queiras guardar muitas alcunhas com uma identificação. É por isso que incluímos um campo seq_no.

Agora, preencha estes valores para a sua tabela:

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

Se quiseres encontrar todos os nomes que você deu à sua amiga id 1 então você pode usar:

select names from nicknames where id = 1;
 7
Author: H. Pauwelyn, 2015-07-26 13:15:18
Além do que todos disseram, sugiro que analises a tua abordagem em termos mais longos do que agora. É actualmente {[3] } o caso de os itens serem únicos. É de momento o caso que o recurso aos itens exigiria uma nova lista. É quase necessário que a lista seja Atualmente curta. Mesmo que eu não tenha os detalhes do domínio, não é muito de um esforço pensar que esses requisitos poderiam mudar. Se você serializar sua lista, você é cozedura em uma inflexibilidade que não é necessária em um design mais normalizado. Btw, isso não significa necessariamente um grande número: muitas relações. Você poderia ter apenas uma tabela de filhos com uma chave estrangeira para o pai e uma coluna de caracteres para o item.

Se ainda quiser seguir esta via de serialização da lista, poderá considerar guardar a lista em XML. Alguns bancos de dados, como o SQL Server, ainda têm um tipo de dados XML. A única razão pela qual sugiro XML é que quase por definição, esta lista tem de ser curta. Se a lista é longa, então serializá-la em geral é uma abordagem horrível. Se você for pela rota CSV, você precisa ter em conta os valores que contêm o delimitador, o que significa que você é obrigado a usar identificadores citados. Persistindo que as listas são curtas, provavelmente não fará muita diferença se você usar CSV ou XML.

 3
Author: Thomas, 2010-06-18 14:39:48

Se precisar de consultar na lista, guarde-a numa tabela.

Se quiser sempre a lista, pode guardá-la como uma lista delimitada numa coluna. Mesmo neste caso, a menos que você tenha razões muito específicas para não, armazená-lo em uma tabela de pesquisa.

 2
Author: hometoast, 2010-06-18 14:28:01

Eu apenas o armazenaria como CSV, se são valores simples, então deve ser tudo o que você precisa (XML é muito descritivo e serializando de/para ele provavelmente seria exagerado, mas isso seria uma opção também).

Aqui está uma boa resposta para como tirar os CSVs com o LINQ.
 1
Author: David Neale, 2017-05-23 10:31:27
Só uma opção não é mencionada nas respostas. Você pode Des-normalizar o seu design DB. Precisas de duas mesas. Uma tabela contém uma lista adequada, um item por linha, outra tabela contém uma lista completa em uma coluna (separada por coma, por exemplo).

Aqui está o design' tradicional ' DB:

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

Aqui está a tabela des-normalizada:

Lists(ListID, ListContent)

A ideia aqui-você mantém a tabela listas usando gatilhos ou código de Aplicação. Sempre que modificar o conteúdo do List_Item, apropriado as linhas nas listas são actualizadas automaticamente. Se leres a maioria das listas, pode funcionar muito bem. Profissionais - você pode ler listas em uma declaração. Contras-atualizações levam mais tempo e esforços.

 1
Author: Alsin, 2010-06-18 15:07:53

Se você realmente quisesse armazená-lo em uma coluna e tê-lo questionável, muitos bancos de dados suportam XML agora. Se não perguntar, você pode armazená-los como valores separados por vírgulas e analisá-los com uma função quando você precisa deles separados. Concordo com todos os outros, no entanto, se você está olhando para usar uma base de dados relacional uma grande parte da normalização é a separação de dados assim. Não estou a dizer que todos os dados se encaixem numa base de dados relacional. Você pode sempre olhar para outros tipos de bases de dados se muitos dos seus dados não se encaixam no modelo.

 0
Author: David Daniel, 2010-06-30 14:42:07

Eu acho que, em certos casos, você pode criar um FALSO "lista" de itens no banco de dados, por exemplo, a mercadoria tem algumas fotos para mostrar seus detalhes, você pode concatenar todas as Identificações de imagens divididas por vírgula e armazenar a seqüência de caracteres para o banco de dados, então você só precisa analisar a seqüência de caracteres quando você precisar dele. Estou trabalhando em um site agora e estou planejando usar desta forma.

 0
Author: Nen, 2016-10-18 16:40:20

Resposta simples: se, e apenas se, tiver a certeza de que a lista será sempre usada como lista, então junte-se à lista no seu fim com um carácter (como '\0') que não será usado no texto nunca, e guarde isso. Depois, quando o recuperar, poderá dividir por '\ 0'. Há, naturalmente, outras maneiras de ir sobre este material, mas esses são dependentes de seu fornecedor de banco de dados específico.

Como exemplo, você pode armazenar JSON em uma base de dados Postgres. Se a sua lista é texto, e você só quero a lista sem mais problemas, é um compromisso razoável.

Outros se aventuraram em sugestões de serialização, mas eu realmente não acho que serialização é uma boa idéia: parte da coisa legal sobre bases de dados é que vários programas escritos em diferentes linguagens podem falar uns com os outros. E programas serializados usando o formato Java não fariam muito bem se um programa Lisp quisesse carregá-lo. Se queres uma boa maneira de fazer este tipo de coisas, normalmente há tipos de array-or-similar disponíveis. Postgres, por exemplo, oferece matriz como um tipo, e permite que você armazenar uma matriz de texto, se é isso que você quer, e há truques similares para MySql e MS SQL usando JSON, e IBM DB2 oferecem um tipo de matriz, bem como (em suas próprias útil documentação). Isto não seria tão comum se não houvesse necessidade disto. O que se perde ao ir por aquela estrada é a noção da lista como um monte de coisas em sequência. Pelo menos nominalmente, as bases de dados tratam os campos como valores únicos. Mas se é só isso que queres, então devias ir em frente. É um julgamento de valor que tens de fazer por ti.
 0
Author: Haakon Løtveit, 2017-05-25 09:50:10