Portanto, de acordo com a resposta de Mehrdad a uma pergunta relacionada , entendi que uma coluna de tabela de banco de dados "adequada" não armazena uma lista. Em vez disso, você deve criar outra tabela que contenha efetivamente os elementos dessa lista e, em seguida, vincular a ela diretamente ou por meio de uma tabela de junção. No entanto, o tipo de lista que desejo criar será composto de itens únicos (ao contrário do fruto da pergunta vinculadaexemplo). Além disso, os itens da minha lista são classificados explicitamente - o que significa que se eu armazenasse os elementos em outra tabela, teria que classificá-los sempre que os acessasse. Finalmente, a lista é basicamente atômica, pois sempre que eu quiser acessar a lista, vou querer acessar a lista inteira em vez de apenas um pedaço dela - então parece bobo ter que emitir uma consulta de banco de dados para reunir pedaços de a lista.
A solução de AKX (link acima) é serializar a lista e armazená-la em uma coluna binária. Mas isso também parece inconveniente porque significa que preciso me preocupar com a serialização e a desserialização.
Existe alguma solução melhor? Se não é nenhuma solução melhor, então por quê? Parece que esse problema deve surgir de vez em quando.
... apenas mais algumas informações para que você saiba de onde estou vindo. Assim que comecei a entender SQL e bancos de dados em geral, fui ligado para LINQ to SQL e agora estou um pouco estragado porque espero lidar com meu modelo de objeto de programação sem ter que pensar sobre como os objetos são consultados ou armazenados no banco de dados.
Obrigado a todos!
John
ATUALIZAÇÃO: Então, na primeira onda de respostas que estou recebendo, vejo "você pode seguir a rota CSV / XML ... mas NÃO!". Agora estou procurando explicações do porquê. Mostre-me algumas boas referências.
Além disso, para lhe dar uma ideia melhor do que estou fazendo: Em meu banco de dados, tenho uma tabela de funções que terá uma lista de pares (x, y). (A tabela também terá outras informações que não têm importância para nossa discussão.) Nunca precisarei ver parte da lista de pares (x, y). Em vez disso, pegarei todos eles e os representarei na tela. Permitirei que o usuário arraste os nós para alterar os valores ocasionalmente ou adicionar mais valores ao gráfico.
Você pode simplesmente esquecer o SQL e escolher uma abordagem "NoSQL". RavenDB , MongoDB e CouchDB vêm à mente como soluções possíveis. Com uma abordagem NoSQL, você não está usando o modelo relacional ... você nem mesmo está restrito a esquemas.
fonte
O que tenho visto muitas pessoas fazerem é isto (pode não ser a melhor abordagem, corrija-me se eu estiver errado):
A tabela que estou usando no exemplo é fornecida abaixo (a tabela inclui apelidos que você deu a suas namoradas específicas. Cada namorada tem um id único):
Suponha que você queira armazenar muitos apelidos sob um id. É por isso que incluímos um
seq_no
campo.Agora, preencha estes valores em sua tabela:
Se você quiser encontrar todos os nomes que deu à sua namorada id 1, você pode usar:
fonte
Resposta simples: Se, e somente se, você tiver certeza de que a lista sempre será usada como uma lista, junte a lista no seu final com um caractere (como '\ 0') que não será usado no texto sempre e armazene-o. Então, quando você recuperá-lo, você pode dividir por '\ 0'. É claro que existem outras maneiras de fazer isso, mas dependem do fornecedor específico do banco de dados.
Como exemplo, você pode armazenar JSON em um banco de dados Postgres. Se a sua lista for de texto e você quiser apenas a lista sem maiores problemas, esse é um meio-termo razoável.
Outros aventuraram-se a sugerir a serialização, mas eu realmente não acho que serializar seja uma boa ideia: parte do bom dos bancos de dados é que vários programas escritos em linguagens diferentes podem conversar entre si. E os programas serializados usando o formato Java não fariam muito bem se um programa Lisp quisesse carregá-lo.
Se você deseja uma boa maneira de fazer esse tipo de coisa, normalmente existem tipos de array ou similares disponíveis. Postgres, por exemplo, oferece array como um tipo e permite que você armazene um array de texto, se for isso que você deseja , e existem truques semelhantes para MySql e MS SQL usando JSON, e o DB2 da IBM oferece um tipo de array também (em seu própria documentação útil ). Isso não seria tão comum se não houvesse necessidade.
O que você perde ao seguir esse caminho é a noção da lista como um monte de coisas em sequência. Pelo menos nominalmente, os bancos de dados tratam os campos como valores únicos. Mas se isso é tudo que você quer, então você deve ir em frente. É um julgamento de valor que você deve fazer por si mesmo.
fonte
Além do que todos disseram, sugiro que você analise sua abordagem em termos mais longos do que agora. Isto é actualmente o caso que os itens são únicos. É actualmente o caso que recorrer os itens exigiria uma nova lista. É quase obrigatório que a lista atualmente seja curta. Mesmo que eu não tenha as especificações do domínio, não é muito forçado pensar que esses requisitos possam mudar. Se você serializar sua lista, estará trabalhando com uma inflexibilidade que não é necessária em um design mais normalizado. A propósito, isso não significa necessariamente um relacionamento Muitos: Muitos completo. Você poderia ter apenas uma única tabela filho com uma chave estrangeira para o pai e uma coluna de caracteres para o item.
Se você ainda deseja seguir este caminho de serializar a lista, considere armazenar a lista em XML. Alguns bancos de dados, como o SQL Server, possuem até mesmo um tipo de dados XML. A única razão pela qual sugiro XML é que, quase por definição, essa lista precisa ser curta. Se a lista for longa, serializá-la em geral é uma abordagem terrível. Se você seguir a rota CSV, precisará levar em conta os valores que contêm o delimitador, o que significa que você é obrigado a usar identificadores entre aspas. Presumindo que as listas são curtas, provavelmente não fará muita diferença se você usar CSV ou XML.
fonte
Eu apenas armazenaria como CSV, se forem valores simples, então deve ser tudo que você precisa (XML é muito prolixo e serializar de / para ele provavelmente seria um exagero, mas essa também seria uma opção).
Esta é uma boa resposta sobre como extrair CSVs com LINQ.
fonte
Se você precisar consultar na lista, armazene-o em uma tabela.
Se você sempre quiser a lista, poderá armazená-la como uma lista delimitada em uma coluna. Mesmo nesse caso, a menos que você tenha motivos MUITO específicos para não fazê-lo, armazene-o em uma tabela de pesquisa.
fonte
Apenas uma opção não mencionada nas respostas. Você pode desnormalizar seu projeto de banco de dados. Portanto, você precisa de duas tabelas. Uma tabela contém a lista apropriada, um item por linha, outra tabela contém a lista inteira em uma coluna (separada por vírgulas, por exemplo).
Aqui está o design de banco de dados 'tradicional':
Aqui está a tabela desnormalizada:
A ideia aqui - você mantém a tabela Lists usando gatilhos ou código do aplicativo. Cada vez que você modifica o conteúdo de List_Item, as linhas apropriadas nas Listas são atualizadas automaticamente. Se você lê principalmente listas, pode funcionar muito bem. Prós - você pode ler listas em uma declaração. Contras - as atualizações exigem mais tempo e esforços.
fonte
Se você realmente deseja armazená-lo em uma coluna e torná-lo consultável, muitos bancos de dados suportam XML agora. Se não estiver consultando, você pode armazená-los como valores separados por vírgula e analisá-los com uma função quando precisar deles separados. Eu concordo com todo mundo, entretanto, se você está procurando usar um banco de dados relacional, uma grande parte da normalização é a separação de dados como esse. Não estou dizendo que todos os dados cabem em um banco de dados relacional. Você sempre pode olhar para outros tipos de banco de dados se muitos dos seus dados não se encaixarem no modelo.
fonte
Acho que em certos casos, você pode criar uma "lista" FALSICA de itens no banco de dados, por exemplo, a mercadoria tem algumas fotos para mostrar seus detalhes, você pode concatenar todos os IDs de fotos divididos por vírgula e armazenar a string em o banco de dados, então você só precisa analisar a string quando precisar. Estou trabalhando em um site agora e estou planejando usar dessa forma.
fonte
Eu estava muito relutante em escolher o caminho que finalmente decidi seguir devido às muitas respostas. Enquanto eles adicionam mais compreensão ao que é SQL e seus princípios, decidi me tornar um fora da lei. Também hesitei em postar minhas descobertas, pois para alguns é mais importante desabafar com alguém que está quebrando as regras do que entender que existem poucas verdades universais.
Eu testei extensivamente e, no meu caso específico, era muito mais eficiente do que usar o tipo de array (generosamente oferecido pelo PostgreSQL) ou consultar outra tabela.
Aqui está minha resposta: Eu implementei com sucesso uma lista em um único campo no PostgreSQL, fazendo uso do comprimento fixo de cada item da lista. Digamos que cada item seja uma cor como um valor hexadecimal ARGB, que significa 8 caracteres. Portanto, você pode criar sua matriz de no máximo 10 itens, multiplicando pelo comprimento de cada item:
Caso o comprimento dos itens da lista seja diferente, você pode preencher o preenchimento com \ 0
NB: Obviamente, esta não é necessariamente a melhor abordagem para o número hexadecimal, uma vez que uma lista de inteiros consumiria menos armazenamento, mas isso é apenas para ilustrar essa ideia de array, fazendo uso de um comprimento fixo alocado para cada item.
O motivo: 1 / Muito conveniente: recupere o item i na substring i * n, (i +1) * n. 2 / Sem sobrecarga de consultas entre tabelas. 3 / Mais eficiente e econômico no lado do servidor. A lista é como um mini blob que o cliente terá que dividir.
Embora eu respeite as pessoas que seguem regras, muitas explicações são muito teóricas e muitas vezes deixam de reconhecer que, em alguns casos específicos, especialmente quando se busca o custo ideal com soluções de baixa latência, alguns pequenos ajustes são mais do que bem-vindos.
"Deus me livre que isso viole algum princípio sagrado do SQL": adotar uma abordagem mais aberta e pragmática antes de recitar as regras é sempre o caminho a percorrer. Caso contrário, você pode acabar como um fanático sincero recitando as Três Leis da Robótica antes de ser obliterado pela Skynet
Não pretendo que esta solução seja uma inovação, nem que seja ideal em termos de legibilidade e flexibilidade de banco de dados, mas certamente pode lhe dar uma vantagem quando se trata de latência.
fonte
Muitos bancos de dados SQL permitem que uma tabela contenha uma subtabela como um componente. O método usual é permitir que o domínio de uma das colunas seja uma tabela. Isso além de usar alguma convenção como CSV para codificar a subestrutura de maneiras desconhecidas para o SGBD.
Quando Ed Codd estava desenvolvendo o modelo relacional em 1969-1970, ele definiu especificamente uma forma normal que não permitiria esse tipo de aninhamento de tabelas. A forma normal foi posteriormente chamada de Primeira Forma Normal. Em seguida, ele mostrou que, para cada banco de dados, existe um banco de dados na primeira forma normal que expressa as mesmas informações.
Por que se preocupar com isso? Bem, os bancos de dados na primeira forma normal permitem o acesso por chave a todos os dados. Se você fornecer um nome de tabela, um valor-chave para essa tabela e um nome de coluna, o banco de dados conterá no máximo uma célula contendo um item de dados.
Se você permitir que uma célula contenha uma lista ou uma tabela ou qualquer outra coleção, agora você não pode fornecer acesso por chave aos subitens, sem retrabalhar completamente a ideia de uma chave.
O acesso por chave a todos os dados é fundamental para o modelo relacional. Sem esse conceito, o modelo não é relacional. Quanto ao motivo pelo qual o modelo relacional é uma boa ideia e quais podem ser as limitações dessa boa ideia, você deve olhar para os 50 anos de experiência acumulada com o modelo relacional.
fonte
você pode armazená-lo como um texto que se parece com uma lista e criar uma função que pode retornar seus dados como uma lista real. exemplo:
base de dados:
E a função do compilador de lista (escrita em python, mas deve ser facilmente traduzível para a maioria das outras linguagens de programação). TEXT representa o texto carregado da tabela sql. retorna a lista de strings da string que contém a lista. se você quiser que ele retorne ints em vez de strings, torne o modo igual a 'int'. Da mesma forma com 'string', 'bool' ou 'float'.
Também aqui está uma função list-to-string, caso você precise.
fonte