AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 109293
Accepted
David Garrison
David Garrison
Asked: 2015-08-07 14:53:21 +0800 CST2015-08-07 14:53:21 +0800 CST 2015-08-07 14:53:21 +0800 CST

Maneira correta de armazenar um valor que pode ser de vários tipos diferentes

  • 772

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, nvarcharou 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.

sql-server database-design
  • 4 4 respostas
  • 10646 Views

4 respostas

  • Voted
  1. Erik
    2015-08-08T09:37:29+08:002015-08-08T09:37:29+08:00

    Com base no que você disse, eu usaria o seguinte esquema geral:

    CREATE TABLE [dbo].[PollQuestion]
    (
        [PollQuestionId] INT NOT NULL PRIMARY KEY IDENTITY,
        [QuestionText] NVARCHAR(150) NOT NULL, -- Some reasonable character limit
        [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
        [Archived] DATETIME2(2) NULL,  -- Remove this if you don't need to hide questions
    )
    CREATE TABLE [dbo].[PollOption]
    (
        [PollOptionId] INT NOT NULL PRIMARY KEY IDENTITY,
        [PollQuestionId] INT NOT NULL,  -- Link to the question here because options aren't shared across questions
        [OptionText] NVARCHAR(50) NOT NULL, -- Some reasonable character limit
        [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
        [Archived] DATETIME2(2) NULL  -- Remove this if you don't need to hide options
    
        CONSTRAINT [FK_PollOption_PollQuestionId_to_PollQuestion_PollQuestionId] FOREIGN KEY ([PollQuestionId]) REFERENCES [dbo].[PollQuestion]([PollQuestionId])
    )
    CREATE TABLE [dbo].[PollResponse]
    (
        [PollResponseId] INT NOT NULL PRIMARY KEY IDENTITY,
        [PollOptionId] INT NOT NULL,
        [UserId] INT NOT NULL,
        [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
        [Archived] DATETIME2(2) NULL,  -- Remove this if you don't need to hide answers
    
        CONSTRAINT [FK_PollResponse_PollOptionId_to_PollOption_PollOptionId] FOREIGN KEY ([PollOptionId]) REFERENCES [dbo].[PollOption]([PollOptionId]),
        CONSTRAINT [FK_PollResponse_UserId_to_User_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User]([UserId])
    )
    

    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.

    CREATE TABLE [dbo].[PollResponse]
    (
        [PollResponseId] INT NOT NULL PRIMARY KEY IDENTITY,
        [PollOptionId] INT NULL,
        [PollQuestionId] INT NOT NULL,
        [UserId] INT NOT NULL,
        [AlternateResponse] NVARCHAR(50) NULL, -- Some reasonable character limit
        [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
        [Archived] DATETIME2(2) NULL,  -- Remove this if you don't need to hide answers
    
        CONSTRAINT [FK_PollResponse_PollOptionId_to_PollOption_PollOptionId] FOREIGN KEY ([PollOptionId]) REFERENCES [dbo].[PollOption]([PollOptionId]),
        CONSTRAINT [FK_PollResponse_UserId_to_User_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User]([UserId])
    )
    

    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:

    CREATE TABLE [dbo].[PollQuestion]
    (
        [PollQuestionId] INT NOT NULL PRIMARY KEY IDENTITY,
        [QuestionText] NVARCHAR(150) NOT NULL, -- Some reasonable character limit
        [QuestionDataTypeId] INT NOT NULL,
        [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
        [Archived] DATETIME2(2) NULL,  -- Remove this if you don't need to hide questions
        -- Insert FK here for QuestionDataTypeId
    )
    CREATE TABLE [dbo].[QuestionDataType]
    (
        [QuestionDataTypeId] INT NOT NULL PRIMARY KEY IDENTITY,
        [Description] NVARCHAR(50) NOT NULL, -- Some reasonable character limit
    )
    

    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.

    • 4
  2. Best Answer
    Olivier Jacot-Descombes
    2015-08-07T15:13:03+08:002015-08-07T15:13:03+08:00

    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? .

    • 2
  3. user126897
    2018-10-27T03:18:32+08:002018-10-27T03:18:32+08:00

    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:

    CHECK 
    (
        CASE WHEN col1 IS NOT NULL THEN 1 ELSE 0 END + 
        CASE WHEN col2 IS NOT NULL THEN 1 ELSE 0 END + 
        CASE WHEN col3 IS NOT NULL THEN 1 ELSE 0 END = 1
    )
    

    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

    • 0
  4. HansLindgren
    2015-08-08T05:24:14+08:002015-08-08T05:24:14+08:00

    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.

    • -2

relate perguntas

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Quais são algumas maneiras de implementar um relacionamento muitos-para-muitos em um data warehouse?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve