Melhor maneira de modelar um singleton em um banco de dados relacional


12

Ao projetar o esquema de banco de dados relacional para aplicativos da Web, geralmente encontro um caso em que acabo criando uma tabela apenas para conter uma linha e apenas uma linha. Parece que esse é o caminho errado para projetá-lo, mas não consigo encontrar nada significativamente melhor, ou esse é obviamente "o caminho certo para fazê-lo".

Um exemplo recente é um site que permite aos usuários controlar manualmente o conteúdo na página inicial. Bem, há apenas uma página inicial. Criei uma tabela com todos os campos necessários para construir a página inicial, como um campo de texto para uma área que continha texto descritivo. Um campo para armazenar o nome de um arquivo de imagem grande. Algumas chaves estrangeiras que apontam para artigos que serão apresentados na página inicial etc. Isso funciona, mas parece errado ter uma tabela com apenas uma linha.

No passado, eu tentei muitos outros designs, como permitir várias linhas na tabela da página inicial e selecionar uma aleatoriamente. Tentei adicionar um campo booleano chamado "ativo" e selecionar aleatoriamente uma das páginas iniciais ativas. Tentei forçar apenas uma linha a estar ativa a qualquer momento na lógica do aplicativo. Tentei nem criar uma tabela da página inicial e ter todos os outros itens, como artigos, para ter campos booleanos com nomes como featured_on_homepage.

Na maioria dos casos, eu poderia criar a página inicial com várias constantes em um arquivo de configurações. O principal problema com o arquivo de configurações é que ele está sob controle do desenvolvedor. Como algo como o conteúdo da página inicial é algo a ser editado pelo usuário, ele precisa estar no banco de dados.

Em muitos sites, não tenho esse problema porque posso criar coisas como a página inicial com uma consulta, como selecionar os cinco artigos mais recentes. Mas quando tenho páginas que são selecionadas manualmente com requisitos rígidos, fica difícil modelá-las no banco de dados. Mas imagine que você tenha uma mesa de fotos e uma mesa de artigos. O requisito é que a página inicial exiba exatamente cinco fotos, exatamente três artigos e dois blocos de texto arbitrário controlados manualmente pelo usuário. Como você modela isso no banco de dados da maneira certa?

Além disso, tenho esse problema de modelagem em muitos outros casos, além de apenas páginas iniciais. É apenas o exemplo mais fácil e mais aplicável que eu poderia inventar.


Não está claro qual é o problema que a tabela de linha única apresenta para você, exceto que, de alguma forma, representa um desperdício de uma tabela. Tem certeza de que está tentando resolver um problema do qual realmente sofre?
David Aldridge

Respostas:


10

Uma abordagem simples seria salvar as propriedades da Página Inicial em uma tabela Propriedades (ou chamá-la de outra coisa) composta de colunas Nome e Valor.

HomePageProperty1 - UserValue1

HomePageProperty2 - UserValue2

Pode não ser uma solução ideal, mas é simples e flexível. Também elimina a tabela com um cenário de linha.


1
Essa abordagem funciona para vários propósitos. Por exemplo, armazenarei informações da versão do esquema, ponteiros de rotação para itens que precisam ser ciclados diariamente etc. A informação da versão do esquema é importante ao diagnosticar o que deu errado. É uma maneira razoável de garantir que um patch seja aplicado a uma correção apenas do banco de dados.
Berin Loritsch

2
+1 - Esse é o layout exato da tabela que nosso Data Architect me forneceu para uma finalidade semelhante.
Ali

3
O problema dessa abordagem é que você precisa representar diferentes tipos de variáveis ​​como colunas diferentes e ter lógica para informar qual coluna usar e quais são obrigatórias. Você não pode definir que um valor booleano é booleano, ou que uma data é uma data, ou que um atributo específico não pode ser nulo, ou deve estar dentro de um intervalo específico ou atender a uma condição - todas as coisas trivialmente simples com uma tabela de linha única.
David Aldridge

3

Não está claro para mim que você tem um problema que precisa resolver.

Uma tabela de linha única não é um problema para o próprio banco de dados e permite aplicar tipos de dados e restrições aos dados.

Não tenho certeza de que você está tentando resolver um problema real, para ser sincero.


2

Parece-me que você está usando um banco de dados para algo que realmente deve ser armazenado como um arquivo.

Sua descrição me lembra muitas páginas da Wiki, onde os usuários podem editar o conteúdo. Nos wikis, ou pelo menos nas implementações que vi, as páginas são mantidas como arquivos.

Isso ajuda você com outros detalhes da Web, como permitir que os usuários armazenem em cache sua página inicial, que é praticamente gratuita se você armazenar as páginas como arquivos, mas você teria que implementar manualmente a lógica para invalidação de cache, se estiver criando o página em cada solicitação com base no conteúdo armazenado no banco de dados.

De qualquer forma, só quero deixar claro que, embora a maioria dos dados persistentes de um aplicativo esteja armazenada em um banco de dados, isso não significa que devemos armazenar tudo lá. Os bancos de dados são apenas uma das ferramentas do nosso comércio. Devemos aprender a fazer bom uso de tantas ferramentas diferentes quanto possível.


2

Não há absolutamente nada de errado em uma tabela com uma linha.

Se isso faz parte do seu design, você deve aplicá-lo. Atribua à tabela uma coluna de identidade, dê uma restrição de exclusividade e adicione uma restrição de coluna para permitir apenas um único valor. Isso garantirá que ninguém poderá adicionar uma segunda linha, o que pode ser catastrófico se as instruções SQL que lêem a tabela (compreensivelmente) não tiverem uma cláusula where.

Se você começar a obter um grande número de colunas, poderá ficar tentado a restringir a tabela e, em vez disso, ter uma linha por item de configuração. Essa não é a melhor ideia, pois você perde a segurança e a validação de tipo. Além disso, você perderia a compatibilidade com a multilocação , o que pode ser importante para você. Uma solução melhor seria repensar o que realmente são suas entidades e ter tabelas de linha única separadas para diferentes entidades.

Sim, não estou apenas dizendo que uma tabela de linha única está OK, mas estou sugerindo que você queira mais de uma delas.


1

Você pode criar uma tabela chamada STATIC_CONTENT e ter colunas para uma chave, bem como o conteúdo, rastreadores ativos / inativos, etc. Em seguida, crie uma linha com a chave "HomePage" e, na sua página inicial, carregue o conteúdo estático dessa chave e exibi-lo. Dessa forma, quando você tiver outro conteúdo estático (sobre página, página de contato etc.), poderá adicionar linhas a essa tabela.


1

Não há nada de errado em ter uma tabela com apenas uma única linha. Se você tiver apenas uma instância de uma determinada entidade, pode ser a maneira mais natural de representá-la.

Mas selecionar uma linha aleatoriamente é errado e é ruim. Se a lógica do seu domínio espera apenas uma única linha, é obviamente um erro nos dados, se houver realmente mais. Portanto, você deve descobrir quem ou o que está gravando dados inválidos no banco de dados e impedir que eles o façam! Dependendo do banco de dados, você provavelmente poderá adicionar uma restrição à tabela para impedir que isso aconteça em primeiro lugar, por exemplo, permitindo apenas um valor específico como chave primária.


0

Apenas para adicionar ao Walter ..

A estrutura da tabela de propriedades deve permitir vários tipos de dados.

Fileds:
PropertyName
PropertyTextValue
PropertyDateValue
PropertyNumericValue
PropertyBoolValue

Com isso, como você garante que apenas um valor de propriedade seja definido por linha? É fácil aplicá-lo no aplicativo, mas e se alguém atualizar o banco de dados manualmente e inserir alguns dados nele?
Apr

0

Parece-me que você poderia abstrair um nível a mais. No final, uma "Página inicial" é uma "Página". Você pode ter diferentes tipos de páginas com as propriedades necessárias. Se você tinha seções em seu site, provavelmente precisará de uma "SectionHomePage", que pode funcionar da mesma forma que uma "Página inicial".

O requisito é que a página inicial exiba exatamente cinco fotos, exatamente três artigos e dois blocos de texto arbitrário controlados manualmente pelo usuário. Como você modela isso no banco de dados da maneira certa?

Vamos tentar assim. Estou adicionando uma tabela ArticlePage para ver como é possível separar as propriedades adequadamente.

PAGES
Id
Title
Description

HOMEPAGES
PageId (FK)
PhotoListLimit
ArticleListLimit
TextBlockListLimit

ARTICLEPAGE
PageId (FK)
ArticleMainQuote
ArticleMainBody
ArticlePhoto1
ArticlePhoto2

Isso funcionaria bem para mim, até funcionaria muito bem para um site grande.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.