Como armazenar status de registro (como pendente, completo, rascunho, cancelado ...)

18

Muitos aplicativos exigem que os registros em suas tabelas tenham um status, como 'completo', 'rascunho', 'cancelado'. Qual é a melhor maneira de armazenar esses status? Para ilustrar o que estou chegando aqui, é um exemplo * muito curto).

Eu tenho um aplicativo de blog simples e cada post tem um status: publicado, rascunho ou pendente.

Do jeito que eu vejo, existem 2 maneiras de modelar isso no banco de dados.

  1. A tabela Postagem possui um campo de texto que inclui o texto de status.
  2. A tabela Post tem um campo de status que contém o ID de um registro na tabela PostStatus

O exemplo do Blog aqui é um exemplo muito simples. Onde uma enumeração (se suportada) pode ser suficiente. No entanto, gostaria que as respostas à pergunta levassem em conta que a lista de status pode mudar a qualquer momento, para que mais possam ser adicionadas ou removidas.

Alguém pode explicar as vantagens / desvantagens de cada um?

Felicidades!

Minha opinião inicial é que é melhor usar outra tabela e procurar o status como melhor para a normalização. Sempre fui ensinado que a normalização é boa para bancos de dados

veganista
fonte
1
Consulte também dba.stackexchange.com/q/11631/630
gbn
O que você quer dizer com "a qualquer momento"? Isso significa como parte da atividade do usuário ou como parte do ciclo de lançamento do software?
Kevin cline
Ambos, em quais casos, qualquer uma das abordagens mencionadas aqui é melhor usada. Portanto, se os usuários puderem adicionar novos status, ou se novos forem adicionados posteriormente no projeto
veganista 15/02/2012
Armazenar o texto no banco de dados pode ser uma boa desnormalização. Eu acho que pode depender de detalhes precisos, por exemplo, com que frequência sua organização altera seus processos (levando a possíveis alterações de status)?
21412 Jaydee
Se os usuários puderem adicionar novos status, isso é outra coisa. Você provavelmente desejará gravar o usuário que criou etc. com o status e definitivamente precisará de outra tabela.
22612 kevin cline

Respostas:

14

Armazenar o status como um índice em outra tabela é uma complicação desnecessária. Armazene o status diretamente na tabela de maneira legível. No código do aplicativo, use constantes ou um tipo de enumeração. Isso resultará em um código de aplicativo mais simples e facilitará a depuração da camada de dados.

Isso não desnormaliza os dados, apenas altera a representação. Se o banco de dados suportar enumerações diretamente, use isso. Caso contrário, use uma restrição para restringir os valores da coluna. Você terá uma restrição de qualquer maneira: uma restrição direta nos valores da coluna ou uma restrição de chave estrangeira.

Sim, pode ser necessário apresentar o status de maneira diferente para diferentes usuários. Esse é um problema de apresentação, a ser resolvido na camada de apresentação, não na camada de persistência.

Kevin Cline
fonte
1
+1, exceto por uma necessidade específica de manter a lista de status no banco de dados, essa geralmente é a maneira mais simples e menos complicada de fazer isso.
GrandmasterB
2
Este é ok, a menos que você começar a mudar a arquitetura de estado ou armazenar datas de mutação
LastTribunal
10

Armazenar o texto de status não é uma boa idéia da IMO, pois alguém pode decidir que "completo" deve ser chamado de "concluído" e, em seguida, você deve atualizar seu banco de dados, examinar o programa se alguém codificou o texto etc.

O que vi em muitos programas é um código numérico (1 = novo, 2 = rascunho, 3 = em validação, 4 = completo, 99 = cancelado) ou um código alfanumérico curto ("NEW", "DRA", "INV "," COM "," CAN "). O posterior torna o código (no programa ou no banco de dados) mais legível por humanos, o que geralmente é uma coisa boa. Por outro lado, os códigos numéricos facilitam a comparação "maior que" ou "menor que", por exemplo

select * from myrecords where status < Status.Complete;
user281377
fonte
Algum idiota também pode identificar o ID.
14502 idiotas
Outra vantagem dos IDs é que você precisa fornecer a localização. Você pode usar seu ID para procurar a sequência de recursos e exibir. Com cordas codificados duros isso não é possível
Armitage
3
Eu não acho que fazer status usando comparações "maior que" ou "menor que" como você mostrou é uma boa idéia. Pode funcionar para aplicativos mais simples, como este exemplo, mas não é bom para aplicativos mais complexos (embora eu esteja certo de que você esteja ciente disso) #
21412
1
@armitage: é perfeitamente possível fazer uma pesquisa usando strings. Nomes de recursos são strings:status.draft=Draught
kevin Cline
veganista: Claro, pode haver dificuldades com comparações maiores que / menores que as comparadas, mas vi sistemas grandes e complexos que fazem isso e vivem.
user281377
4

As três regras dos bancos de dados relacionais:

  1. Normalizar
  2. Normalizar
  3. Normalizar

Portanto, sua pergunta responde a si mesma. Mantenha o status dentro de sua própria tabela e use GUID / UUIDs como seu ID . Os GUIDS indexados são muito rápidos e corrigem os problemas intrínsecos ao aumento de números. Com um ID, você pode fazer coisas legais, como solicitar ao DB todas as postagens concluídas usando o ID e, como você está trabalhando dentro do paradigma relacional do banco de dados, é muito rápido. Se você tiver apenas um campo, o banco de dados precisará percorrer todas as linhas e fazer uma comparação de texto, talvez com munging, e isso é muito lento.

Os nomes dos status das postagens podem mudar, mais informações sobre o status das postagens podem ser exibidas na tabela, tudo funciona se você normalizar .

Por exemplo, você pode adicionar níveis de status como informações adicionais, o que permitiria a comparação mencionada pela munição. Mas eles não dependem da chave para o posicionamento, permitindo a reorganização do nível de status sem prejudicar a integridade do banco de dados. Você também pode inserir níveis adicionais, o que é um truque se você tiver o nível associado à chave de incremento automático.

Spencer Rathbun
fonte
As razões que você indicou aqui são exatamente as razões pelas quais estou usando outra tabela para armazenar meus status. A principal razão pela qual eu fiz essa pergunta é ver se às vezes é bom usar um campo de texto mais simples.
veganista 14/02/12
@ Liam Apenas se normalizar para um campo de texto. Ou seja, se o seu campo de texto depender apenas da chave primária e você estiver pesquisando as coisas com base na chave primária , com o campo de texto chegando. Um banco de dados relacional é sobre relacionamentos, você tem um aqui, portanto, ele precisa ser definido. Uma das poucas exceções é se você estiver manipulando dados sujos de uma fonte externa e não tiver tempo para modelá-los completamente. Evite isso, se possível.
Spencer Rathbun
couros olhos, lamentando os GUIDs que nunca vai voltar
sq33G
Você deveria ter escrito "três teorias de bancos de dados relacionais". A teoria nem sempre é prática. Geralmente, é mais eficiente armazenar um código de status diretamente no registro ao qual está relacionado. Se você não precisar procurá-lo para usá-lo, a remoção da associação a outra tabela economizará muito processamento desperdiçado.
Suncat2000
Voto negativo devido às informações incorretas sobre os tipos de coluna x verificações de tabela completa.
igorrs
3

Sim, você deve ir com a opção 2, com uma tabela PostStatus.

Além de todas as vantagens mencionadas em outras respostas.

Tendo em mente que os status precisam ser adicionados ou removidos, você pode ter uma coluna "ativado" na tabela PostStatus; portanto, se o status for removido, marque a coluna "ativado" como "N", para que você possa adicione ou remova status e também os registros existentes permanecerão sem problemas.

Mr Spark
fonte
1

Eu gostaria de acrescentar às respostas perspicazes que, para normalização total, uma alteração no status de uma entidade é modelada em uma entidade separada, por exemplo, denominada 'statusChange'.

Você precisaria de uma associação extra com a entidade statusChange, mas terá a possibilidade de adicionar informações extras, como o ator que está realizando a alteração, possíveis comentários sobre o motivo da alteração e uma data na qual a statusChange é executada e, possivelmente, mesmo quando torna-se eficaz.

Dibbeke
fonte
0

Usar texto para status na tabela de registros provavelmente não seria uma boa ideia, pois isso pode mudar e seria difícil executar qualquer verificação de integridade dos dados ao inserir / atualizar. Se você estiver utilizando um DBMS com um tipo de dados enum, poderá usá-lo (o desempenho provavelmente não será comprometido ... dependendo).

Se o seu status precisar de metadados (descrição, criada por, nome amigável, ...), será necessário armazenar os status em uma tabela separada e ter uma chave de status na sua tabela de registros (certifique-se de usar uma chave estrangeira). O ID não precisa necessariamente ser um número, apenas o PK da tabela de status. Além disso, se os status estiverem em sua própria tabela, você poderá compartilhá-los entre os tipos de registro (tabelas), se aplicável. Eu não me preocuparia com problemas de desempenho com um JOIN na tabela de status.

Faça o que fizer, evite status mágicos (1 para ativo, 2 para excluído, ...). Isso depende de documentação e tradição, que sempre tendem a se perder em uma linha do tempo suficientemente grande. Se você estiver usando IDs numéricos, verifique se há uma associação textual em algum lugar do seu banco de dados.

smp7d
fonte
Se você não está preocupado com o desempenho, provavelmente está sacrificando a escalabilidade. É impossível para os computadores evitar status mágicos: 0 e 1 são intrinsecamente mágicos.
Suncat2000
0

Depende do objetivo do design do banco de dados.

Se você projetar o banco de dados simplesmente para suportar o aplicativo (ou seja, os objetos (código) são os principais de todos), usar uma enumeração (ou uma enumeração psuedo para classes que não as suportam) e armazenar o nome da enumeração é um boa idéia, porque você ainda controla os valores permitidos através da enum e também facilita a leitura da tabela quando é forçado a visualizar os dados brutos (o que não ocorre com frequência se o código realmente governa tudo). Mas se a enumeração estiver sinalizada. Então eu costumo armazenar o valor de enumeração (inteiro).

ElGringoGrande
fonte
-1

O status é muito importante: sempre que você obtiver informações sobre postagens, será necessário obtê-lo ou filtrará as postagens por status. Se você tiver status em outra tabela, precisará fazer junções para obter essas informações e, portanto, o desempenho será comprometido. Definitivamente você deve ter status na mesma tabela. E coloque um índice nele! Você ainda pode usar números inteiros como status ou, talvez, campo enum.

dxvargas
fonte
-2

A solução correta é usar um armazenamento / fonte de eventos com CQRS ou uma blockchain. O problema com a captura de eventos em um RDB é que o RDB armazena uma captura instantânea de um único evento no tempo, e coisas como "Status / Estados" são sequências de mutações que evoluem ao longo do tempo

LastTribunal
fonte
Se você quiser votar no meu post, faça um caso. Else você é apenas um lemming espírito suave que tem muito pouco espaço fora da caixa
LastTribunal