Toda tabela deve ter uma chave primária substituta / artificial de campo único?

33

Entendo um benefício das chaves substitutas / artificiais em geral - elas não mudam e isso pode ser muito conveniente. Isso é verdade se eles são de campo único ou múltiplo - desde que sejam 'artificiais'.

No entanto, às vezes parece uma questão de política ter um campo inteiro com auto incremento como a chave primária de cada tabela. Essa é sempre a melhor idéia para ter uma chave de campo único e por que (ou por que não)?

Para ficar claro, essa pergunta não é artificial ou natural - mas se todas as chaves artificiais devem ser de campo único

Jack Douglas
fonte
1
veja também dba.stackexchange.com/a/112632/1396
Jack Douglas

Respostas:

28

Vou dizer não, nem sempre, mas na maioria das vezes sim. .

Estas são algumas circunstâncias em que você não precisa de uma chave substituta ou artificial:

  • Mesas de interseção puras . Se não houver risco de a interseção ser o alvo de uma chave estrangeira e se houver pouco ou nenhum risco de atrair atributos independentes (por exemplo, algo que não seja FK para as duas tabelas pai), você poderá usar a combinação de FKs como PK com confiança.
  • Tabelas de pesquisa com chaves de negócios estáticas . Se você tiver uma
    tabela de pesquisa com uma chave comercial exclusiva, fixada externamente ao seu
    negócio e com chance zero de mudar para qualquer
    finalidade prática, o uso direto da chave comercial poderá
    simplificar as coisas. Um exemplo pode ser uma lista de
    códigos de estado ou província ou uma lista de números padrão ANSI, etc.
  • Tabelas contendo dados consolidados de várias fontes independentes . Se o seu sistema possui muitas fontes de dados que devem ser agrupadas em uma única tabela, digamos na matriz, às vezes você precisa de uma chave composta que inclua o valor da chave do sistema de origem e um código indicando qual era o sistema de origem.

Há também algumas situações em que a chave substituta de número inteiro crescente monotonicamente fiel não é ideal. Você pode ter chaves que são substitutas alfanuméricas. Estes podem incluir:

  • Situações em que você precisa mesclar dados de várias fontes independentes. Para evitar colisões de chaves, você pode usar GUIDs em vez de chaves de IDENTIDADE.
  • Situações em que você é forçado a usar representações de teclas não numéricas. Digamos que você tenha um banco de dados de placas. Sua chave pode ser o valor alfanumérico em vez de um número puro.
  • Situações em que algum requisito externo força você a aplicar compactação ao seu valor-chave. Em vez de usar 10 dígitos para um int32, você pode usar seis dígitos base 36.

Por que na maioria das vezes sim? A resposta mais fundamental para essa pergunta é que é um inferno se você precisar modificar um valor de chave primária em qualquer tabela. Como quase tudo o que um usuário pode ver ou tocar está sujeito a uma atualização em algum momento, o uso de um valor de chave visível está convidando o inferno. Usar uma chave substituta impedirá você de cair nessa armadilha.

Dito isto, lembre-se de que há espaço para a YAGNI aplicar esse conceito. Você não precisa forçar tabelas de códigos com chaves de IDENTIDADE em todos os cantos do seu esquema, caso alguém decida que o símbolo do sexo masculino na tabela de funcionários precisa mudar de M para X ou algo parvo.

Joel Brown
fonte
"O uso de uma chave substituta impedirá que você caia nessa armadilha" A questão não é sobre substitutos versus naturais, mas sobre substitutos de campo único vs.
Jack Douglas
Como você reconheceu em um comentário sua própria resposta, concordamos em discordar do território quando se trata do que é prudente no design do banco de dados. Dada a sua edição, eu não faria a distinção entre chaves substitutas e chaves naturais, portanto, meu segundo ponto final está atrasado. Meus outros pontos sobre quando alguém pode divergir da abordagem clássica de identidade / sequência ainda permanecem.
Joel Brown
Eu não mudei a pergunta como você pode ver a partir da história, a ênfase apenas acrescentado onde eu pensei que ele iria ajudar skim-leitores
Jack Douglas
12

Não.

Eu diria que certamente existem casos em que as chaves de campo único são inferiores às chaves compostas, pelo menos para fins de chaves estrangeiras . Isso não quer dizer que você também não deve ter uma chave substituta de campo único, se preferir, mas eu pessoalmente prefiro que a chave mais usada como destino de uma chave estrangeira seja chamada de chave primária.

Tentarei ilustrar meu argumento nos seguintes exemplos, nos quais:

  • brand é marca de carro, por exemplo, Ford, Toyota etc
  • dealer é uma concessionária física, ligada a uma marca (por exemplo, uma concessionária Ford que vende apenas Ford)
  • model é o tipo de carro, por exemplo, Ford Focus, Ford Fiesta, etc.
  • stock é a contagem atual de carros no pátio de cada concessionária

Se criarmos uma chave substituta de campo único para dealere da modelseguinte forma:

create table brand( brand_id integer primary key );

create table dealer( dealer_id integer primary key, 
                     brand_id integer references brand )

create table model( model_id integer primary key, 
                    brand_id integer references brand )

create table stock( model_id integer references model, 
                    dealer_id integer references dealer, 
                    quantity integer,
                      primary key(model_id, dealer_id) )

então é possível inserir uma linha stockque liga um Ford dealera um modelo "Toyota". Adicionando brand_id references branda stocksó torna o problema pior. Por outro lado, se mantivermos a chave estrangeira como parte da chave primária, da seguinte maneira:

create table brand( brand_id integer primary key );

create table dealer( brand_id integer references brand, 
                     dealer_id integer, 
                       primary key(brand_id, dealer_id) )

create table model( brand_id integer references brand, 
                    model_id integer, 
                      primary key(brand_id, model_id) )

create table stock( brand_id integer, 
                    model_id integer, 
                    dealer_id integer, 
                    quantity integer,
                      primary key(brand_id, model_id, dealer_id),
                      foreign key(brand_id, model_id) references model,
                      foreign key(brand_id, dealer_id) references dealer )

agora a regra de que os revendedores "Ford" só podem estocar carros "Ford" é aplicada naturalmente pelo modelo.

Observe que no exemplo de 'chaves compostas', dealer_idpode ou não ser exclusivo, de acordo com a preferência. Ele não precisa ser único (ou seja, uma chave alternativa), mas muito pouco é perdido ao fazê-lo (talvez um pouco de espaço de armazenamento) e pode ser muito útil, por isso é o modo como geralmente o configuro, por exemplo:

create table dealer( brand_id integer references brand, 
                     dealer_id serial unique, 
                       primary key(brand_id, dealer_id) )
Jack Douglas
fonte
3
Considerando as condições usuais de que os exemplos não são necessariamente perfeitos de todos os ângulos, eu diria que esse tipo de design é particularmente frágil. Embora exista algo satisfatório em encontrar uma maneira de usar o DRI para impor regras de negócios, isso também tira parte de sua capacidade de responder a alterações. Se a Toyota comprar a Ford, ou mesmo se um revendedor da Ford decidir vender um Toyota usado, suas regras de negócios orientadas a DRI darão uma dor de cabeça na manutenção.
Joel Brown
1
Portanto, "suas regras de negócios podem mudar". Isso é verdade para qualquer regra de negócios e sempre será potencialmente difícil re-modelar. Geralmente me dizem quais são as regras de negócios - não as decido por mim.
Jack Douglas
1
Você está dizendo que o DRI não deve ser usado para impor regras de negócios? Não é a única coisa que o DRI faz? - até mesmo chaves estrangeiras simples são regras de negócios impostas pelo DRI.
Jack Douglas
4
É claro que o DRI impõe regras de negócios. Você precisa decidir quais regras serão aplicadas no código e quais no seu esquema. As alterações de esquema são quase sempre mais difíceis que as alterações de código. Existem dois tipos de regras de negócios que podem entrar no seu modelo de dados. Um pertence a ele e outro não. A natureza fundamental dos dados importantes para os seus negócios não muda muito. As maneiras específicas pelas quais você opera com esses dados são muito mais voláteis . Uma regra como os carros têm um fabricante pertence ao modelo de dados. Uma regra como revendedores nunca venderá duas marcas de carros não.
Joel Brown
4
"Alterações de esquema são quase sempre mais difíceis que alterações de código" IMO, o oposto é verdadeiro. Na verdade, eu discordo de praticamente tudo o que você acabou de dizer, mas duvido que haja algum motivo para discutir o assunto com você, então deixarei assim.
Jack Douglas
12

"depende"

Sim: os campos substitutos IDENTITY / AUTONUMBER são bons quando a chave natural é ampla e não numérica. Nota: isso pressupõe a fusão de "PK" e índice clusterizado que ocorre por padrão no SQL Server e Sybase etc.

Não: muitas / muitas tabelas quando as 2 chaves pai são suficientes. Ou quando a chave natural é curta e de comprimento fixo, por exemplo, código da moeda

Obviamente, um ORM de cabeçalho (leia-se: (n) Hibernate) pode superar essas regras ...

Editar: lendo a pergunta novamente

Uma tabela many / many com 2 chaves pai substitutas terá uma PK de várias colunas.
No entanto, ele não precisa de outra coluna substituta.

Se uma tabela tiver uma chave substituta (IDENTITY etc), ela não precisará ter várias colunas.

Você pode ter uma super chave que inclua o substituto, mas isso seria impor outras regras (por exemplo, subtipos )

gbn
fonte