Eu tenho uma tabela de respostas e uma tabela de perguntas .
A tabela Answers tem um valor, mas dependendo da pergunta, esse valor pode ser bit
, nvarchar
ou number
(até agora). A Questão tem uma noção de qual deve ser o tipo de valor de resposta pretendido.
Será importante analisar esses valores de resposta em um ponto ou outro, pois os números, pelo menos, precisarão ser comparados.
Para um pouco mais de contexto, as perguntas e possíveis respostas (normalmente um tipo de dados permitido para uma entrada do tipo caixa de texto) são fornecidas por alguns usuários em uma espécie de pesquisa. As respostas são então fornecidas por outros usuários especificados.
Algumas opções que considerei são:
A. XML ou string que é analisado de forma diferente dependendo do tipo pretendido (que é acompanhado na pergunta)
B. Três tabelas separadas que fazem referência (ou são referenciadas por) à tabela Resposta e são unidas com base no tipo pretendido. Nesse caso, não tenho certeza da melhor maneira de configurar as restrições para garantir que cada pergunta tenha apenas uma resposta ou se isso deve ser deixado para o aplicativo.
C. Três colunas separadas na tabela Resposta que podem ser recuperadas com base no tipo pretendido.
Eu ficaria feliz em obter algumas informações sobre os prós e contras dessas abordagens ou abordagens alternativas que não considerei.
Com base no que você disse, eu usaria o seguinte esquema geral:
Você realmente não se importa se a resposta é um número, data, palavra, etc. porque os dados são uma resposta a uma pergunta, não algo sobre o qual você precisa operar diretamente. Além disso, os dados só têm significado no contexto da pergunta. Como tal, um nvarchar é o mecanismo legível por humanos mais versátil para armazenar os dados.
A pergunta e as possíveis respostas seriam coletadas do primeiro usuário e inseridas nas tabelas PollQuestion e PollOption. O segundo usuário que responder às perguntas selecionará em uma lista de respostas (verdadeiro/falso = lista de 2). Você também pode expandir a tabela PollQuestion para incluir o ID do usuário do criador, se apropriado, para rastrear as perguntas que eles criam.
Em sua IU, a resposta que o usuário seleciona pode ser vinculada ao valor PollOptionId. Junto com o PollQuestionId você pode verificar se a resposta é válida para a pergunta rapidamente. A resposta deles, se válida, seria inserida na tabela PollResponse.
Existem alguns problemas potenciais, dependendo dos detalhes do seu caso de uso. Se o primeiro usuário quiser usar uma pergunta de matemática e você não quiser oferecer várias respostas possíveis. Outra situação é se as opções fornecidas pelo usuário inicial não forem as únicas opções que o segundo usuário pode escolher. Você pode retrabalhar esse esquema da seguinte maneira para dar suporte a esses casos de uso adicionais.
Eu provavelmente também adicionaria uma restrição de verificação para garantir que uma opção seja fornecida ou uma resposta alternativa, mas não ambas (opção e resposta alternativa), dependendo de suas necessidades.
Editar: Tipo de dados de comunicação para AlternateResponse.
Em um mundo perfeito, poderíamos usar o conceito de genéricos para lidar com vários tipos de dados para o AlternateReponse. Infelizmente, não vivemos em um mundo perfeito. O melhor compromisso que posso pensar é especificar qual tipo de dados AlternateResponse deve estar na tabela PollQuestion e armazenar o AlternateReponse no banco de dados como um nvarchar. Abaixo está o esquema de pergunta atualizado e a nova tabela de tipo de dados:
Você pode listar todos os tipos de dados disponíveis para criadores de perguntas selecionando nesta tabela QuestionDataType. Sua interface do usuário pode fazer referência ao QuestionDataTypeId para selecionar o formato adequado para o campo de resposta alternativo. Você não está limitado aos tipos de dados TSQL, portanto, "Número de telefone" pode ser um tipo de dados e você obterá a formatação/mascaramento apropriado na interface do usuário. Além disso, se necessário, você pode lançar seus dados para os tipos apropriados por meio de uma declaração de caso simples para fazer qualquer tipo de processamento (seleção, validação, etc.) nas respostas alternativas.
Realmente depende de como seu front-end acessa os dados.
Se você estiver usando um mapeador O/R, concentre-se no design orientado a objetos de suas classes, não no design do banco de dados. O banco de dados apenas espelha o design da classe. O design exato do banco de dados depende do mapeador O/R e do modelo de mapeamento de herança que você está usando.
Se você estiver acessando as tabelas diretamente por meio de conjuntos de registros, tabelas de dados, leitores de dados ou similares, uma coisa simples a fazer é converter os valores em uma string usando uma cultura invariável e armazená-los em uma coluna de texto simples . E, claro, use a mesma cultura novamente para converter o texto de volta para os tipos de valor especializados ao ler os valores.
Como alternativa, você pode usar uma coluna por tipo de valor. Temos unidades de terabyte hoje!
Uma coluna XML é possível, mas provavelmente acrescenta mais complexidade em comparação com a coluna de texto simples e faz praticamente a mesma coisa, ou seja, serializar/desserializar.
Tabelas unidas separadas são a maneira normalizada correta de fazer as coisas; no entanto, eles também adicionam alguma complexidade.
Mantenha simples.
Veja também minha resposta para Questionnaire database design - qual caminho é melhor? .
Dê uma olhada em O que há de tão ruim no EAV, afinal? por Aaron Bertrand para algumas informações sobre o modelo EAV.
Provavelmente será melhor de várias maneiras ter uma coluna para cada tipo de dados em vez de XML ou várias tabelas.
A parte da restrição é fácil:
Existem muitas perguntas e respostas neste site marcadas como eav , e provavelmente outras em que o autor da pergunta não sabia usar esse termo em sua pergunta.
Eu recomendo fortemente a leitura deles, pois eles provavelmente cobrirão todos os prós e contras (isso evita que as pessoas os repitam aqui, quando na realidade eles não mudaram).
Resposta baseada nos comentários das perguntas deixados por Aaron Bertrand
Acho que o problema é pensado demais ou há algumas restrições adicionais sobre o motivo pelo qual certas respostas podem ser mais aceitáveis do que outras. Atualmente, parece não haver nenhuma evidência de que a resposta teria que ser processada de alguma forma pelo banco de dados, mas apenas como um campo de log.
Eu usaria um NVARCHAR (MAX) e deixaria o front-end lidar com o armazenamento/recuperação do conteúdo. Possivelmente um campo de bit IS_CORRECT onde o frontend poderia armazenar se a resposta estiver correta.