Convenção de nomenclatura de chave primária / chave estrangeira [fechada]

95

Em nosso grupo de desenvolvimento, temos um intenso debate sobre a convenção de nomenclatura para chaves primárias e estrangeiras. Existem basicamente duas escolas de pensamento em nosso grupo:

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

ou

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

Prefiro não duplicar o nome da tabela em nenhuma das colunas (portanto, prefiro a opção 1 acima). Conceitualmente, é consistente com muitas das práticas recomendadas em outras linguagens, onde você não usa o nome do objeto em seus nomes de propriedade. Eu acho que nomear a chave estrangeira EmployeeID(ouEmployee_ID pode ser melhor) informa ao leitor que é a IDcoluna da EmployeeTabela.

Alguns outros preferem a opção 2, onde você nomeia a chave primária prefixada com o nome da tabela para que o nome da coluna seja o mesmo em todo o banco de dados. Eu entendo esse ponto, mas agora você não pode distinguir visualmente uma chave primária de uma chave estrangeira.

Além disso, acho que é redundante ter o nome da tabela no nome da coluna, porque se você pensar na tabela como uma entidade e uma coluna como uma propriedade ou atributo dessa entidade, você pensa nela como o atributo ID do Employee, não o EmployeeIDatributo de um funcionário. Eu não pergunto ao meu colega de trabalho o que é PersonAgeouPersonGender é é. Eu pergunto a ele qual é a sua idade.

Então, como eu disse, é um debate intenso e continuamos e continuamos sobre isso. Estou interessado em obter algumas novas perspectivas.

Jeremy
fonte
1
questão duplica esta stackoverflow.com/questions/208580/…
Mike Henke
1
Eu li mais de 10 perguntas semelhantes e finalmente descobri que as 3 principais respostas aqui são boas: stackoverflow.com/a/465146/781695
usuário
Apenas uma observação lateral: a escolha 2 permitiria que você 'se conectasse naturalmente'. Caramba, por que não fazer isso na escolha 1 adicionando 'Employee.ID como EmployeeID'. Mas a melhor prática parece ser 'Junte-se' usando 'ON Employee.ID = Event.EmployeeID'.
Leo
Em ambas as situações, você terá que usar alias (ou 'table_name.column_name') em uma ou mais filas porque você está, em ambos os casos, repetindo nomes de coluna.
Please_Dont_Bully_Me_SO_Lords

Respostas:

52

Realmente não importa. Nunca me deparei com um sistema em que haja uma diferença real entre as opções 1 e 2.

Jeff Atwood escreveu um ótimo artigo há algum tempo sobre esse assunto. Basicamente, as pessoas debatem e argumentam com mais fúria aqueles tópicos sobre os quais não se pode provar que estão errados. Ou, de um ângulo diferente, aqueles tópicos que só podem ser vencidos por meio de argumentos de resistência baseados no estilo obstrucionista.

Escolha um e diga a eles para se concentrarem nos problemas que realmente afetam seu código.

EDITAR: Se você quiser se divertir, peça-lhes que especifiquem detalhadamente por que seu método é superior para referências de tabela recursivas.

Russell Steen
fonte
26
+1, para o bom senso ... Há coisas mais importantes para discutir. Então, faça do meu jeito (escolha 2)
Charles Bretana
5
E, para DRI de autorreferência, quando há mais de um FK que se refere ao mesmo PK, você TEM que violar os dois "padrões", uma vez que as duas colunas FK não podem ter o mesmo nome ... por exemplo, EmployeeTable com EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, etc. etc ...
Charles Bretana
75

Se as duas colunas têm o mesmo nome em ambas as tabelas (convenção # 2), você pode usar a sintaxe USING em SQL para economizar digitação e alguns ruídos clandestinos:

SELECT name, address, amount
  FROM employees JOIN payroll USING (employee_id)

Outro argumento a favor da convenção nº 2 é que essa é a forma como o modelo relacional foi projetado.

O significado de cada coluna é parcialmente transmitido rotulando-o com o nome do domínio correspondente.

Steven Huwig
fonte
4
A sintaxe e a semântica SQL fornecem, na verdade, uma boa pista de como ela deve ser usada. por exemplo, USING syntax significa que colunas com o mesmo domínio devem ter o mesmo nome, NULL = NULL -> NULL significa que NULL é "desconhecido" ao invés de "não aplicável", e ON UPDATE CASCADE significa que as chaves precisam apenas ser únicas, não imutáveis.
Steven Huwig,
6
Melhor ainda, ele permite que este: SELECT name, address, amount FROM employees NATURAL JOIN payroll.
dia em
5
Eu não usaria junção natural no código implantado, porque é mais frágil no caso de adições de esquema. Mas para consultas interativas, é ótimo.
Steven Huwig
3
+1, mas sempre há uma exceção. Por exemplo, se você tiver duas colunas na folha de pagamento que são chaves estrangeiras para o funcionário (uma referência à pessoa que está sendo paga, a segunda ao gerente com autoridade orçamentária, por exemplo). Mas não podemos nomear as duas chaves estrangeiras employee_id.
Bill Karwin
1
A palavra-chave "usando" é específica do MySql. Não funciona em T-SQL - infelizmente.
birdus
12

Acho que depende de como o aplicativo é elaborado. Se você usa ORM ou projeta suas tabelas para representar objetos, a opção 1 pode ser para você.

Gosto de codificar o banco de dados como sua própria camada. Eu controlo tudo e o aplicativo apenas chama procedimentos armazenados. É bom ter conjuntos de resultados com nomes de colunas completos, especialmente quando há muitas tabelas unidas e muitas colunas retornadas. Com esse tipo de aplicativo, gosto da opção 2. Gosto muito de ver os nomes das colunas coincidirem nas junções. Trabalhei em sistemas antigos onde eles não combinavam e foi um pesadelo,

KM.
fonte
4
+1 por ter que descobrir junções com nomes de coluna não correspondentes
Raj More,
4
em "sistemas antigos" a desvantagem de nomes longos de 8 caracteres que dói muito mais do que isso. Estou disposto a me arriscar e especular que ter o PK com o nome ID não foi a causa primária do pesadelo nos sistemas antigos com os quais você estava lidando. Além disso, "sugava em sistemas antigos" é usado muuuuito frequentemente no desenvolvimento de software, especialmente bancos de dados. Eu geralmente vejo pessoas justificando qualquer prática A, com base na maneira como funcionava em sua experiência em um sistema de banco de dados lançado há mais de 10 anos.
Russell Steen,
2
de hoje estado da arte aplicações serão velha porcaria em poucos anos. você pode até reescrever a interface ou usar os dados em outra plataforma, mas seus dados (incluindo os nomes das colunas) precisarão resistir ao teste do tempo.
KM.
2
Então, as pessoas há 20 anos deveriam ter de alguma forma usado nomes de coluna que fizessem sentido hoje, embora eles tivessem apenas 8 caracteres? Os formatos de armazenamento de dados mudaram drasticamente nos últimos 20 anos e mudarão novamente nos próximos 20. Não há como demonstrar que sua preferência resistirá ao teste do tempo melhor do que o outro método listado. "nomes de colunas" podem ser "porcaria velha" quando as pessoas começarem a ter essa discussão em 20 anos, à medida que nossa capacidade de armazenar e manipular dados melhorar. As tabelas são uma construção humana que representam de forma imperfeita as relações de dados ...
Russell Steen
1
Obrigado pela resposta intelectual bem fundamentada.
Russell Steen
3

Nenhuma das convenções funciona em todos os casos, então por que ter uma? Use o senso comum...

por exemplo, para a tabela de auto-referência, quando há mais de uma coluna FK que faz referência ao PK da mesma tabela, você TEM que violar os dois "padrões", já que as duas colunas FK não podem ter o mesmo nome ... , EmployeeTable with EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, ...

Charles Bretana
fonte
1
+1 para a resposta real do objetivo técnico
DVK
Uma resposta boa e aplicável, mas os argumentos para a resposta de Dems erram o alvo.
JYelton
3

Concordo que há pouco a escolher entre eles. Para mim, uma coisa muito mais significativa sobre qualquer um dos padrões é a parte "padrão".

Se as pessoas começarem a 'fazer suas próprias coisas', elas devem ser amarradas por suas forças. NA MINHA HUMILDE OPINIÃO :)

MatBailie
fonte
3
+1 para reconhecer que a consistência é mais importante do que estar "certo" (neste caso)
Russell Steen
-1 por tentar aplicar uma "consistência tola". Antigo provérbio chinês diz: "Uma consistência tola é um hobgoblin para mentes simples."
Charles Bretana
@charles: em um mundo onde pessoas diferentes mantêm o código umas das outras, geralmente quando o escritor sai e a documentação está obsoleta ou inexistente, esta não é uma consistência tola. Estou tão feliz por não trabalhar com você ...
MatBailie
@Dems, sem intenção de ofender, mas isso é tolice, por duas razões. 1) Existem cenários comuns e claramente compreendidos onde QUALQUER padrão teria de ser violado. (veja minha resposta para exemplos e 2) porque nesta questão, pelo menos, um padrão agregaria muito pouco valor, exceto para fazer as pessoas que gostam de padrões se sentirem mais confortáveis ​​...
Charles Bretana
1
você poderia argumentar que "ID" é mais consistente - porque assim que você introduzir o idioma inglês "carID" na tabela "cars" ou na tabela "car"? "ID da ovelha" na tabela "ovelhas" ou "ovelhas" - as coisas começam a ficar inconsistentes. Se você se limitar a "ID" e nomes de tabela singulares - isso não é apenas consistente, mas também funciona bem com muitos ORMs / requer menos configuração (por exemplo, Dapper Contrib)
niico
3

Você considerou o seguinte?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee
Wouter
fonte
3
Eu não suporto quando as pessoas votam e não dão uma razão para isso. Esta é uma resposta completamente válida, seja palatável ou não para alguns, é uma questão diferente, mas isso é subjetivo e não requer uma votação negativa.
Jeremy
1
Obrigado por apontar isso. Também estou interessado nos motivos pelos quais você não usaria esse formato. E tenho certeza de que haverá boas razões ...
Wouter
Esta é a melhor saída, pois você não terá que usar table_name.column_nameem consultas e não precisará usar alias para nomes de coluna se não tiver nomes repetidos ...
Please_Dont_Bully_Me_SO_Lords
1
Isso pode ser considerado uma forma de notação húngara. Portanto, considere os argumentos a favor e contra isso.
Fred
2

A convenção que usamos onde trabalho é muito próxima de A, com a exceção de que nomeamos as tabelas no plural (ou seja, "funcionários") e usamos sublinhados entre a tabela e o nome da coluna. A vantagem disso é que, para se referir a uma coluna, ela pode ser "funcionários _ id" ou "funcionários.id", dependendo de como você deseja acessá-la. Se você precisar especificar de qual tabela a coluna está vindo, "workers.employees _ id" é definitivamente redundante.

Jarett Millard
fonte
Ainda não decidi se gosto de nomes de tabelas pluralizados. Ao usar o singular, as consultas parecem ter uma leitura melhor ("employee.name" em oposição a "workers.name"). Mesmo em junções, parece que funciona melhor, pois você está juntando registros únicos a outra tabela. Mas os nomes de tabelas pluralizados parecem mais precisos quando se pensa na tabela, ao invés da consulta. Vou ficar com o singular, pois é isso que usamos, mas acho que também é o caminho certo a seguir (embora, novamente, muitos discordem)
MatBailie,
Sim. É mais uma preferência pessoal e / ou o que quer que você esteja acostumado a ver, eu acho.
Jarett Millard,
2

Se você está olhando para o código do aplicativo, não apenas para consultas de banco de dados, algumas coisas parecem claras para mim:

  1. As definições de tabela geralmente são mapeadas diretamente para uma classe que descreve um objeto, portanto, devem ser singulares. Para descrever uma coleção de um objeto, geralmente acrescento "Array" ou "List" ou "Collection" ao nome no singular, pois mais claramente do que o uso de plurais indica não apenas que se trata de uma coleção, mas que tipo de coleção isto é. Nessa visão, vejo um nome de tabela não como o nome da coleção, mas o nome do tipo de objeto do qual é uma coleção. Um DBA que não escreve o código do aplicativo pode perder esse ponto.

  2. Os dados com os quais lido frequentemente usam "ID" para fins de identificação não relacionados à chave. Para eliminar a confusão entre "ID" s de chave e "ID" não chave, para o nome da chave primária, usamos "Chave" (é isso que é, não é?) Prefixada com o nome da tabela ou uma abreviatura de o nome da tabela. Este prefixo (e eu reservo isso apenas para a chave primária) torna o nome da chave único, o que é especialmente importante porque usamos nomes de variáveis ​​que são iguais aos nomes das colunas do banco de dados, e a maioria das classes tem um pai, identificado pelo nome de a chave pai. Isso também é necessário para garantir que não seja uma palavra-chave reservada, o que é "Chave" por si só. Para facilitar a manutenção de nomes de variáveis-chave consistentes e para fornecer programas que fazem junções naturais, as chaves estrangeiras têm o mesmo nome que é usado na tabela na qual são a chave primária. Eu encontrei mais de uma vez programas que funcionam muito melhor dessa forma usando junções naturais. Sobre este último ponto, admito um problema com as tabelas de autorreferência, que usei. Nesse caso, eu faria uma exceção à regra de nomenclatura de chave estrangeira. Por exemplo, eu usaria ManagerKey como uma chave estrangeira na tabela Employee para apontar para outro registro nessa tabela.

Bruce Patin
fonte
Muitos mapeadores relacionais de objetos (ORM), como o Entity Framework, permitem mapear uma tabela para uma classe com um nome diferente. Isso permite que você tenha uma classe chamada "Usuário" e uma tabela chamada "Usuários".
Fred
2

Gosto da convenção nº 2 - ao pesquisar este tópico e encontrar esta questão antes de postar a minha, encontrei o seguinte problema:

Estou selecionando * em uma tabela com um grande número de colunas e unindo-a a uma segunda tabela que, da mesma forma, possui um grande número de colunas. Ambas as tabelas têm uma coluna "id" como chave primária, o que significa que tenho que escolher especificamente cada coluna (até onde eu sei) para tornar esses dois valores únicos no resultado, ou seja:

SELECT table1.id AS parent_id, table2.id AS child_id

Embora usar a convenção nº 2 signifique que ainda terei algumas colunas no resultado com o mesmo nome, agora posso especificar qual id preciso (pai ou filho) e, como sugeriu Steven Huwig, a USINGinstrução simplifica ainda mais as coisas.

JYelton
fonte
2
SELECT *é um não-não para (a maioria) das consultas de produção, de qualquer maneira, então isso não é muito motivo para escolher um padrão de nomenclatura.
P Daddy
1
Não discordando: você poderia fornecer um link para o motivo disso? Não gosto da ideia de ter que manter os nomes de 80 colunas na minha consulta.
JYelton
Não consigo encontrar um link no momento (difícil de pesquisar no Google por "*"), mas irei delinear os pontos básicos: (1) alterações na (s) tabela (s) podem impactar negativamente seu aplicativo, (2) pode ser ruim para o desempenho e (3) especificar explicitamente quais dados você realmente precisa pode tornar seu código mais fácil de entender. Esses pontos podem se expandir, e há exceções (como aludi), mas isso não é apropriado aqui. Se você postar isso como uma nova pergunta, eu (e outros) ficaremos felizes em elaborar mais.
P Daddy
2
Eu posso fazer isso. Eu percebo o benefício do desempenho, mas tenho que considerar o investimento de tempo ao editar o código. Estou sempre procurando maneiras de melhorar a interação entre o aplicativo e o banco de dados. Obrigado.
JYelton
1
Não tenho certeza se SELECT *é um não-não para a maioria das consultas de produção. Se aumenta significativamente a velocidade de desenvolvimento e torna o código muito mais conciso e legível - permitindo que você se concentre em assuntos mais importantes - por que não SELECT *? Depende muito das circunstâncias de cada situação e é uma troca entre muitos fatores. Uma regra raramente se ajusta a tudo.
niico
2

Sempre usei userId como PK em uma tabela e userId em outra tabela como FK. estou pensando seriamente em usar userIdPK e userIdFK como nomes para identificar um do outro. Isso vai me ajudar a identificar PK e FK rapidamente ao olhar as tabelas e parece que vai limpar o código ao usar PHP / SQL para acessar dados, tornando-os mais fáceis de entender. Especialmente quando alguém olha meu código.

Ross
fonte
1

Eu uso a convenção nº 2. Estou trabalhando com um modelo de dados legado agora, onde não sei o que significa em uma determinada tabela. Onde está o mal em ser prolixo?

Pôneis OMG
fonte
1

Que tal nomear a chave estrangeira

role_id

onde papel é o papel que a entidade referenciada tem em relação à tabela em questão. Isso resolve o problema de referência recursiva e vários fks para a mesma tabela.

Em muitos casos, será idêntico ao nome da tabela referenciada. Nestes casos, torna-se idêntico a uma de suas propostas.

Em qualquer caso, ter longos argumentos é uma má ideia

Jens Schauder
fonte
0

"Onde em" ordem INNER JOIN do funcionário ON order.employee_id = employee.id "há necessidade de qualificação adicional?".

Não há necessidade de qualificação adicional porque a qualificação de que falei já existe.

“a razão pela qual um usuário de negócios se refere a Order ID ou Employee ID é para fornecer contexto, mas em um nível de banco de dados você já tem contexto porque está se referindo à tabela”.

Por favor, diga-me, se a coluna se chama 'ID', então como isso "referindo [sic] à mesa" é feito exatamente, a não ser qualificando esta referência para a coluna ID exatamente da maneira que eu falei?


fonte