Melhor maneira de armazenar um valor que pode ser de vários tipos

10

Gostaria de re-fazer uma pergunta de uma maneira mais direta e geral:

Como você cria uma tabela para armazenar valores que podem ser vários tipos diferentes?

No meu caso, os valores fornecem diagnósticos sobre um evento. Ex: Evento ocorreu -> Armazene leituras de vários CPs que contêm informações pertinentes sobre o evento. Os CLPs podem monitorar qualquer tipo de dados.

Alguns exemplos em que posso pensar:

  • Crie uma coluna para todos os tipos possíveis e crie outra coluna para indicar qual coluna usar
    • Ex: Cols: IntVal, StrVal, BoolVal, Tipo. Vals: null, null, True, "BOOL"
  • Armazene os valores, não importa o que seja um varchar
Praia Jared
fonte

Respostas:

9

Parece que você já foi informado de que está se afastando no caminho para o modelo EAV . Dê uma olhada na imagem aqui para saber por que o modelo EAV deve ser evitado a praticamente todos os custos.

Bill Karwin, autor responsável pela imagem acima, escreveu um livro "Antipatterns SQL: Evitando as Armadilhas da Programação de Banco de Dados" e dedica o primeiro capítulo ao anti-padrão EAV. Ele também é um grande incentivador nesse grupo e grande no StackOverflow (para problemas de banco de dados).

Meu conselho seria ter uma tabela para cada tipo de resultado e depois usar VIEWs para combiná-los quando necessário.

Como exemplo, você poderia ter

CREATE TABLE char_result
(
  question_id INT,
  user_id INT,
  cresult CHAR,
  result_correct BOOLEAN (or equivalent in your RDBMS)
  ..
  <other stuff>
  ..
);

Faça o mesmo para num_result, exceto nresult INT (FLOAT ... tanto faz) por cresult - a mesma idéia para VARCHAR & c.

Em seguida, crie VIEWs sobre suas diferentes tabelas de resultados para result_correct(e outros campos - number_of_attempts... etc.), quaisquer que sejam seus outros campos. Nesse caso, você está comparando cálculos de igual com igual e não realizando equivalentes a adicionar população à altitude, conforme a imagem hilária mencionada acima!

Vérace
fonte
Em contrapartida a Bill, escrevi a favor do EAV aqui: sqlblog.com/blogs/aaron_bertrand/archive/2009/11/19/…
Aaron Bertrand
Eu não acho que ter vários tipos possíveis para a mesma coluna lógica constitua um EAV. Eu acho que ele está procurando um tipo de "variante / objeto". Isso é muito mais fácil com algumas colunas do que uma tabela por tipo. Isso parece muito inconveniente. E depois que a visualização é criada, é realmente a mesma coisa que criar os tipos na mesma tabela em primeiro lugar.
usr
@usr Eu estaria interessado em ver sua solução.
Jared Beach
2
Apenas uma coluna por tipo me parece adequada. Eu fiz isso assim no passado. É a solução menos ruim. Aqui está outro argumento: e se houvesse duas colunas de tipo variável. A solução desta resposta requer um número quadrático de tabelas. Pode-se dividi-lo em uma tabela básica e mais N * M tabelas ... Isso não parece certo.
usr
@usr não é um problema com sua solução que nenhuma dessas colunas possa ter NOT NULL? Pessoalmente, acredito muito em ter uma NOT NULLrestrição sempre que possível .
Vérace 6/06/16
2

Acho que se fosse absolutamente necessário armazenar um valor dessa maneira em um banco de dados relacional, eu usaria uma solução como as colunas JSON do Microsoft SQL Server .

Praia Jared
fonte