Meu professor de t-sql nos disse que nomear nossa coluna PK "Id" é considerada uma prática ruim sem maiores explicações.
Por que nomear uma coluna PK da tabela "Id" é considerado uma prática ruim?
Meu professor de t-sql nos disse que nomear nossa coluna PK "Id" é considerada uma prática ruim sem maiores explicações.
Por que nomear uma coluna PK da tabela "Id" é considerado uma prática ruim?
Respostas:
Vou dizer: não é realmente uma prática ruim (e mesmo que seja, não é tão ruim assim).
Você pode argumentar (como Chad apontou) que pode mascarar erros como na consulta a seguir:
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.Id = car.ManufacturerId
JOIN models mod
ON mod.Id = car.ModelId
JOIN colors col
ON mfg.Id = car.ColorId
mas isso pode ser atenuado facilmente, não usando aliases minúsculos para os nomes de suas tabelas:
SELECT *
FROM cars
JOIN manufacturer
ON manufacturer.Id = cars.ManufacturerId
JOIN models
ON models.Id = cars.ModelId
JOIN colors
ON manufacturer.Id = cars.ColorId
A prática de SEMPRE usar abreviações de três letras parece muito pior para mim do que usar o nome da coluna id
. (Caso em questão: quem realmente abreviaria o nome da tabela cars
com a abreviação car
? Que finalidade isso serve?)
O ponto é: seja consistente. Se sua empresa usa o ID e você geralmente cometer o erro acima, adquira o hábito de usar nomes de tabelas completos. Se sua empresa proíbe a coluna Id, aguarde e use a convenção de nomenclatura que preferir.
Concentre-se em aprender coisas que são realmente más práticas (como várias subconsultas correlacionadas aninhadas) em vez de ponderar sobre questões como essa. A questão de nomear suas colunas como "ID" está mais próxima de ser uma questão de gosto do que de uma má prática.
NOTA PARA OS EDITORES: O erro nesta consulta é intencional e está sendo usado para fazer uma observação. Leia a resposta completa antes de editar.
cars
-> car
. Graças a Deus - você salvou meus dedos). Não leia muito profundamente.
cars
e manufacturer
. Um é plural, o outro não. Se as pessoas querem escolher o banco de dados, essa é a má prática a ser adotada.
Porque quando você tem uma tabela com uma chave estrangeira, não pode nomear essa chave estrangeira "Id". Você tem o nome da tabela TableId
E então sua junção parece
SELECT * FROM cars c JOIN manufacturer m ON m.Id = c.ManufacturerId
E, idealmente, sua condição deve ter o mesmo nome de campo em cada lado
SELECT * FROM cars c JOIN manufacturer m ON m.ManufacturerId = c.ManufacturerId
Portanto, embora pareça redundante nomear o ID como ManufacturerId, é menos provável que você tenha erros nas condições de junção, à medida que os erros se tornam óbvios.
Parece simples, mas quando você junta várias tabelas, é mais provável que você cometa um erro, encontre a tabela abaixo ...
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.Id = car.ManufacturerId
JOIN models mod
ON mod.Id = car.ModelId
JOIN colors col
ON mfg.Id = car.ColorId
Considerando que, com a nomeação adequada, o erro se destaca ...
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.ManufacturerId = car.ManufacturerId
JOIN models mod
ON mod.ModelId = car.ModelId
JOIN colors col
ON mfg.ManufacturerId = car.ColorId
Outro motivo para nomear o ID como "ruim" é que, quando você está consultando informações de várias tabelas, precisará renomear as colunas do Id para poder distingui-las.
SELECT manufacturer.Id as 'ManufacturerId'
,cars.Id as 'CarId'
--etc
FROM cars
JOIN manufacturer
ON manufacturer.Id = cars.Id
Com nomes precisos, isso é menos problemático
SELECT * FROM cars c JOIN manufacturer m ON manufacturer.Id = c.ManufacturerId
. Eu uso id
há anos e nunca achei o que você descreveu como um problema real.
SELECT manufacturer.id FROM ...
. Toda dificuldade resultante id
pode ser superada com muita facilidade, tornando-a simplesmente uma questão de gosto.
A biblioteca ActiveRecord do Ruby e o GORM do Groovy usam "id" para a chave substituta por padrão. Eu gosto dessa prática. Duplicar o nome da tabela em cada nome de coluna é redundante, tedioso para escrever e mais tedioso para ler.
Nomes de colunas comuns ou de chave como "Nome" ou "Id" devem ser prefixados com o Nome da Tabela.
Ele remove a ambiguidade, mais fácil de procurar, significa muito menos aliases da coluna quando os dois valores de "ID" são necessários.
Uma coluna menos usada ou de auditoria ou sem chave (por exemplo, LastUpdatedDateTime) não importa
name
e id
? Por que não ter todas as colunas prefixadas com o nome da tabela? Parece arbitrário escolher esses dois nomes para determinar um prefixo. Conceitualmente, você deve ter a tabela para ter o contexto de uma coluna de qualquer maneira. Por que não usar esse nome tabela para esclarecer a consulta: Person.Name, Animal.Name, Part.Name, ...
Esta discussão está encerrada, mas eu gostaria de acrescentar que a IMO não usar Id
é uma prática ruim. A Id
coluna é especial; é a chave primária. Qualquer tabela pode ter qualquer número de chaves estrangeiras, mas pode ter apenas uma chave primária. Em um banco de dados em que todas as chaves primárias são chamadas Id
, assim que você olha para a tabela, sabe exatamente qual coluna é a chave primária.
Acredite, há meses que passo o dia inteiro todos os dias trabalhando em muitos bancos de dados grandes (Salesforce), e a melhor coisa que posso dizer sobre os esquemas é que todas as tabelas têm uma chave primária chamada Id
. Posso garantir que absolutamente nunca me confundo sobre associar uma chave primária a uma chave estrangeira porque o PK é chamado Id
. Outra coisa que as pessoas não mencionaram é que as tabelas podem ter nomes tolos e longos Table_ThatDoesGood_stuff__c
; esse nome já é ruim o suficiente porque o arquiteto teve uma ressaca na manhã em que pensou nessa tabela, mas agora você está me dizendo que é uma prática ruim não chamar a chave primária Table_ThatDoesGood_stuff__cId
(lembrando que os nomes das colunas SQL geralmente não diferenciam maiúsculas de minúsculas).
Para ser sincero, os problemas com a maioria das pessoas que ensinam programação de computadores são que eles não escrevem uma linha de código de produção há anos, se é que alguma vez, e não têm idéia do que realmente faz um engenheiro de software em funcionamento. Espere até começar a trabalhar e decida o que você acha que é uma boa ideia ou não.
Não considero uma prática ruim. A consistência é rei, como sempre.
Eu acho que é tudo sobre contexto. Por si só, no contexto da tabela, "id" significa exatamente o que você espera, um rótulo para ajudar a identificá-lo exclusivamente contra outros que, de outra forma, poderiam ser (ou parecer) idênticos.
No contexto de junções, é sua responsabilidade construí-las de maneira a torná-las legíveis para você e sua equipe. Assim como é possível dificultar as coisas com fraseado ou nomeação, é igualmente possível construir uma consulta significativa com o uso eficaz de aliases e até comentários.
Da mesma forma que uma classe Java chamada 'Foo' não tem suas propriedades prefixadas por 'Foo', não se sinta obrigado a prefixar seus IDs de tabela com nomes de tabela. Geralmente, é claro no contexto qual é o ID a que se refere.
BOOM, pergunta respondida.
Agora, diga ao seu professor que SO pratica um design ruim do banco de dados.
PostTypeId -> PostTypes.Id
; AcceptedAnswerId -> Answers.Id
; OwnerUserId -> Users.Id
. Por que uma prática tão fácil deve ser considerada "ruim"?
Isso torna difícil (e confuso) realizar uma junção natural na mesa, portanto, sim, é ruim, se não muito ruim.
A junção natural é um artefato antigo do SQL Lore (ou seja, álgebra relacional) que você pode ter visto um destes: ⋈ talvez em um livro de banco de dados. O que eu quero dizer é que o Natrual Join não é uma nova idéia SQL distorcida, mesmo que pareça levar uma eternidade para os DBMS implementá-la; portanto, não é uma idéia distorcida para você implementá-la, pode até ser irracional você ignorar sua existência hoje em dia.
Bem, se você nomear o ID de toda a chave primária, perderá a facilidade e a simplicidade da junção natural. select * from dudes natural join cars
precisará ser escrito select * from dudes inner join cars where cars.dudeid = dudes.id
ou select * from dudes inner join cars where dudes.carid = cars.id
. Se você é capaz de fazer uma junção natural, ignora o que realmente é a relação, o que, acredito, é bastante impressionante.
Há uma situação em que colar "ID" em todas as tabelas não é a melhor idéia: a USING
palavra - chave, se for suportada. Nós o usamos frequentemente no MySQL.
Por exemplo, se você tiver fooTable
uma coluna fooTableId
e barTable
uma chave estrangeira fooTableId
, suas consultas poderão ser construídas da seguinte forma:
SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)
Ele não apenas salva a digitação, mas é muito mais legível em comparação com a alternativa:
SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)
USING
palavra-chave é suportada pelo banco de dados postgres / mysql / sqlite, significa menos digitação que algumas das outras respostas listam como razão para o uso id
e, finalmente, na minha opinião subjetiva, é mais legível.
Por que não perguntar ao seu professor?
Pense nisso: quando todas as colunas PK de suas tabelas são nomeadas ID
, o uso delas como chaves estrangeiras é um pesadelo.
Os nomes das colunas precisam ser semanticamente significativos. ID
é genérico.
id
sozinho não significa nada, especialmente no contexto de uma chave estrangeira para outra tabela. Isso não tem nada a ver com, classes
e tudo a ver com um bom design básico básico de banco de dados relacional.
table.id
é uma maneira perfeitamente aceitável de se referir a um id
campo. Prefixar o nome do campo com o nome da tabela é redundante.
O ID está incorreto pelos seguintes motivos:
Se você faz muitas consultas de relatórios, sempre precisa usar o alias das colunas para ver as duas. Portanto, torna-se uma perda de tempo quando você pode nomear o nome corretamente para começar. Essas consultas complexas são difíceis o suficiente (escrevo consultas que podem ter centenas de linhas) sem o ônus adicional de fazer um trabalho desnecessário.
Está sujeito a causar erros de código. Se você usar um banco de dados que permita o uso da junção natural (não que eu ache que você deva usá-lo, mas quando houver recursos disponíveis, alguém os usará), você se juntará à coisa errada se conseguir um desenvolvedor que a use.
Se você estiver copiando associações para criar uma consulta complexa, é fácil esquecer de alterar o alias para o desejado e obter uma associação incorreta. Se cada ID for nomeado após a tabela em que está, geralmente você receberá um erro de sintaxe. Também é mais fácil identificar se a junção em uma consulta complexa está incorreta se o nome do pPK e o nome do FK corresponderem.
ID
não me convencem.
Existem algumas respostas que se aproximam do que eu consideraria o motivo mais importante para não usar "id" como o nome da coluna da chave primária em uma tabela: a saber, consistência e ambiguidade reduzida.
No entanto, para mim, o principal benefício é alcançado pelo programador de manutenção, em particular aquele que não estava envolvido no desenvolvimento original. Se você usou o nome "PersonID" para o ID na tabela Person e o usou consistentemente como uma chave estrangeira, é trivial escrever uma consulta no esquema para descobrir quais tabelas têm PersonID sem precisar inferir que "PersonID" é o nome usado quando é uma chave estrangeira. Lembre-se, certo ou errado, os relacionamentos de chave estrangeira nem sempre são impostos em todos os projetos.
Há um caso de borda em que uma tabela pode precisar ter duas chaves estrangeiras na mesma tabela, mas, nesses casos, eu colocaria o nome da chave original como o nome do sufixo da coluna, para que uma correspondência curinga,% PersonID, pudesse encontrar facilmente essas instâncias também.
Sim, muito disso poderia ser conseguido com o padrão de ter "id" e saber usá-lo sempre como "tableNameID", mas isso exige que você saiba que a prática está em vigor e que depende dos desenvolvedores originais seguirem com menos prática padrão intuitiva.
Embora algumas pessoas tenham apontado que são necessárias algumas teclas extras para escrever os nomes mais longos das colunas, eu diria que escrever o código é apenas uma pequena fração da vida ativa do programa. Se salvar o pressionamento de teclas do desenvolvedor era o objetivo, os comentários nunca deveriam ser escritos.
Como alguém que passou muitos anos mantendo grandes projetos com centenas de tabelas, eu preferiria fortemente nomes consistentes para uma chave entre tabelas.
Companies
tabela tenha 2 chaves estrangeiras em uma Persons
tabela. Um representa o presidente da empresa; o outro representa o tesoureiro da empresa. Você realmente chamaria as colunas PersonID1
e PersonID2
? Seria muito mais descritivo chamá-los PresidentID
e TreasurerID
. Acho que é muito mais fácil de ler inner join Person AS Presidents ON Company.PresidentID = Presidents.ID
do queinner join Person AS Person1 ON Company.PersonID1 = Person1.PersonID
CompanyOfficer
ou CompanyPerson
que permita um relacionamento muitos para muitos entre Company
e Person
com informações adicionais sobre a natureza do relacionamento. Se fosse para implementá-lo na Company
tabela, usaria os nomes das colunas PresidentPersonID
e TreasurerPersonID
preservaria a parte * PersonID do nome ao adicionar o descritor adicional. inner join Person as Presidents on Company.PresidentPersonID = Presidents.PersonID
A prática de usar o ID como campo de chave primária leva à prática em que o ID é adicionado a todas as tabelas. Muitas tabelas já possuem informações exclusivas que identificam exclusivamente um registro. Use ISTO como chave primária e não um campo de ID que você adiciona a cada tabela. Essa é uma das bases dos bancos de dados relacionais.
E é por isso que usar o id é uma prática ruim: o id geralmente não é uma informação apenas um aumento automático.
considere as seguintes tabelas:
PK id | Countryid | Countryname
1 | 840 | United States
2 | 528 | the Netherlands
O que há de errado com esta tabela é que ela permite que o usuário adicione outra linha: Estados Unidos, com o código do país 840. Isso acabou com a integridade relacional. É claro que você pode impor exclusividade em colunas individuais ou simplesmente usar uma chave primária que já esteja disponível:
PK Countryid | Countryname
840 | United States
528 | the Netherlands
Dessa forma, você usa as informações que já possui como chave primária, que está no centro do design de banco de dados relacional.
Não acho que seja uma prática ruim se usada corretamente. É comum ter um campo de ID de incremento automático chamado "ID" que você nunca precisa tocar e usar um identificador mais amigável para o aplicativo. Pode ser um pouco complicado escrever código, from tableA a inner join tableB b on a.id = b.a_id
mas esse código pode ser escondido.
Como preferência pessoal, costumo prefixar o ID com o nome da entidade, mas não vejo um problema real ao usar apenas Id
se ele for tratado inteiramente pelo banco de dados.
O ID é bastante comum, e acho que isso não confundiria ninguém. Você sempre vai querer conhecer a mesa. Colocar nomes de campos no código de produção sem incluir uma tabela / alias é uma prática ruim. Se você está preocupado demais em poder digitar rapidamente consultas ad hoc, está por sua conta.
Espero que ninguém desenvolva um banco de dados sql em que ID seja uma palavra reservada.
CREATE TABLE CAR (ID);
Cuida do nome do campo, da chave primária e dos incrementos automáticos em 1 começando com 1, tudo em um pequeno e agradável pacote de 2 caracteres. Ah, e eu chamaria isso de CARS, mas se vamos economizar com o pressionamento de teclas e quem realmente acha que uma mesa chamada CAR terá apenas um?
Car
representa um Table
onde cada Row
um representa um único Car
. A chamada Cars
muda a semântica e mostra uma completa falta de entendimento dos princípios básicos da teoria relacional formal. O Rails é um excelente exemplo de alguém que sabia o suficiente para ser perigoso .
Essa pergunta foi repetida várias vezes, mas pensei em acrescentar minha opinião.
Uso id para significar que esse é o identificador de cada tabela; portanto, quando ingresso em uma tabela e preciso da chave primária, ingresso automaticamente na chave primária.
O campo id é um incremento automático, sem sinal (o que significa que nunca preciso definir seu valor e não pode ser negativo)
Para chaves estrangeiras, eu uso tablenameid (novamente uma questão de estilo), mas a chave primária na qual ingresso é o campo id da tabela, portanto, a consistência significa que sempre posso verificar consultas facilmente
id é curto e doce também
Convenção adicional - use letras minúsculas para todos os nomes de tabelas e colunas, para que nenhum problema seja encontrado devido a maiúsculas e minúsculas
Outra coisa a considerar é que, se o nome da chave primária for diferente do nome da chave estrangeira, não será possível usar certas ferramentas de terceiros.
Por exemplo, você não conseguiria carregar seu esquema em uma ferramenta como o Visio e produzir ERDs precisos.
Acho que as pessoas aqui cobrem praticamente todos os aspectos, mas quero acrescentar que "id" não é e não deve ser lido como "identificador", é mais um "índice" e certamente não indica nem descreve a identidade da linha. (Talvez eu tenha usado palavras erradas aqui, corrija-me se o fizesse)
É mais ou menos como as pessoas leem os dados da tabela e como escrevem seu código. Pessoalmente, e provavelmente essa é a maneira mais popular que vejo com mais frequência é que os codificadores escrevem a referência completa como table.id
, mesmo que não precisem fazer união ou união. Por exemplo:
SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>
Dessa forma, você pode traduzi-lo para o inglês como "Dê-me a cor e o modelo do carro que está numerado como". e não como "Dê-me a cor e o modelo do carro identificado como número". O ID não representa o carro de forma alguma, é apenas o índice do carro, um número de série, se você desejar. Assim como quando você deseja pegar o terceiro elemento de uma matriz.
Então, para resumir o que eu queria adicionar, é apenas uma questão de preferência e a maneira descrita de ler SQL é a mais popular.
No entanto, existem alguns casos em que isso não é usado, como (um exemplo muito mais raro) quando o ID é uma string que está realmente descrevendo. Por exemplo id = "RedFordMustang1970"
ou algo semelhante. Eu realmente espero poder explicar isso pelo menos para ter uma idéia.