İnsanlar neden bir kimlik sütunu için “Id” adını kullanmamalarını önerir?


68

IdTablolarımın kimlik sütununun adını kullanmamam öğretildi , ancak son zamanlarda bunu zaten kullandım çünkü verinin gerçekte ne olduğu hakkında basit, kısa ve çok açıklayıcı.

İnsanların Idtablo adının önekini önerdiğini gördüm , ancak bu sadece SQL sorgularını yazan kişi için daha fazla iş yapıyor gibi görünüyor. CustomerProductIdveyaAgencyGroupAssignementId

Üçüncü taraf bir satıcı, bizim Identkullanmaktan kaçınmak için bize bir şey yaratmak için işe başladık, aslında tüm kimlik sütunlarını kullanmamaya karar verdi Id. İlk başta bunu Idbir anahtar kelime olduğu için yaptıklarını düşündüm , ancak içine baktığımda, bunun Idbizim kullandığımız SQL Server 2005’te bir anahtar kelime olmadığını gördüm .

Peki neden insanlar Idbir kimlik sütunu için isim kullanılmamasını tavsiye ediyor ?

Düzenleme: Açıklığa kavuşturmak için, hangi adlandırma kuralının kullanılacağını ya da bir adlandırma kuralını diğerine kullanacak argümanları sormuyorum. Sadece neden Idkimlik sütunu adı için kullanılmaması gerektiğini bilmek istiyorum .

Ben tek bir programcıyım, dba değil ve bana göre veritabanı verilerimi saklayabileceğiniz bir yer. Genellikle küçük uygulamalar oluşturduğum ve genellikle veri erişimi için bir ORM kullandığım için, kimlik alanı için ortak bir alan adıyla çalışmak çok daha kolay. Bunu yaparak neyi kaçırdığımı bilmek istiyorum ve bunu yapmamam için gerçekten iyi nedenler varsa.


10
BF zaten bunfight burada: programmers.stackexchange.com/q/114728/5905 Birçoğumuz (okudum: ben) içine
girdik

Kimlik sütununun adı olarak "id" kullanılmasına karşı gerçekten böyle bir kural var mı? Ruby on Rails için standart bir ORM olan ActiveRecord, kongre ile tam olarak bunu yapıyor. ar.rubyonrails.org
200_success

1
@ 200_success Veri tabanı düzeyinde, evet. Bu veritabanı sitesi, ORM sitesi değil;)
JNK

Yanıtlar:


46

Tablo adı ön ekinin çok iyi nedenleri var.

Düşünmek:

TableA (id int identity, stringdata varchar(max))

TableB (id int identity, stringdata varchar(max))

Her iki tabloda da var DELETEolan TableAkayıtlardan almak istiyoruz . Yeterince kolay, biz sadece bir yapacağız INNER JOIN:

DELETE a
FROM 
  TableA A
INNER JOIN 
  TableB B
    ON b.id = B.id

.... ve hepsini sildik TableA. Yanlışlıkla B'nin kimliğini kendisiyle karşılaştırdık - her kayıt eşleşti ve her kayıt silindi.

Alanlar adlandırılmış olsaydı TableAIdve TableBIdbu imkansız olurdu ( Invalid field name TableAid in TableB).

Şahsen idbir tablodaki adı kullanma konusunda bir sorunum yok , ancak yanlışlıkla yanlış alanla karşılaştırmaktan ve üflemeyi önlemek için tablo adıyla (veya o TableAzamanlar insanlar da PeopleIdiyi çalışacaksa varlık adıyla) önsözlemek gerçekten daha iyi bir uygulama bir şey.

Bu aynı zamanda, alanların nereden geldiği ve çok sayıda soruyla uzun sorgularda ortaya çıktığını da açıkça ortaya JOINkoymaktadır.


10
Yani temelde hatalardan korunmak için bir adlandırma kuralı mı? Ben kullanarak düşünürdüm begin transactionve commit transaction(IMO) daha iğrenç bir adlandırma şeması kullanarak daha iyi uygulama olacaktır
Rachel

13
@Rachel: bu 1. netlik 2. gereksiz sütun takma adlarından kaçının 3. JOIN..USING'e izin verin 4. Setlerde değil, tek nesnelerde çalışan PHP maymunlarını sinirlendirin
gbn

4
@Rachel Sorguyu yazarken hatayı fark etmediyseniz ve hemen çalıştırmadan önce, taahhütte bulunmadan önce farkına varmanız mümkün değildir. Bu şey olur, neden daha olası?
Andy

7
@Andy SELECTÇalıştırmadan önce kayıtlarımı bulmak için her zaman bir iş yaparım DELETEve ifadeyi çalıştırdıktan sonra satır sayısının taahhüt etmeden önce beklediğimden olduğunu her zaman doğrularım.
Rachel

5
@Rachel Sizin için çalışan bir şeyin olması güzel. Bunu herkesin yapmasını sağlayabilir misin?
Andy

36

Çoğunlukla yabancı anahtarların muazzam bir acı haline gelmesini engellemek. İki tablonuz olduğunu varsayalım: Müşteri ve Müşteri Adresi. Her ikisi için de birincil anahtar, bir kimlik (int) sütunu olan id adlı bir sütundur.

Şimdi müşteri adınızı Müşteri Adresinden referans almanız gerekir. Sütun kimliğini adlandıramazsınız, açıkçası, customer_id ile gidersiniz.

Bu birkaç soruna yol açar. Öncelikle, "id" sütununun ne zaman ve ne zaman "customer_id" olarak adlandırıldığını sürekli olarak hatırlamanız gerekir. Ve bunu karıştırırsanız, ikinci soruna yol açar. Bir düzine kadar katılımcının olduğu büyük bir sorunuz varsa ve herhangi bir veri döndürmüyorsa, Where's Waldo'yu oynayıp bu yazım tipini araştırırken eğlenin:

ON c.id = ca.id

Vay be, olmalıydı ON c.id = ca.customer_id. Ya da daha iyisi, kimlik sütunlarınızı tanımlayıcı olarak adlandırın, öyle olabilir ON c.customer_id = ca.customer_id. Daha sonra yanlışlıkla yanlış tablo takma adını başka bir yerde kullanırsanız, customer_id bu tablodaki bir sütun olmayacak ve boş sonuçlar ve daha sonra kodun işaretlenmesi yerine güzel bir derleme hatası alırsınız.

Bir tablodan diğerine tek bir tablodan birden fazla yabancı anahtar ilişkisine ihtiyacınız varsa, ancak tüm birincil anahtarların "kimliği" isimlendirilmesinin bir faydası yok.


27

İşte tüm birincil anahtarlar için ortak bir ad kullanmamak için sözleşmeden elde edilen avantajlarla ilgili tüm cevapların bir özeti:

  • Daha az hata, kimlik alanları aynı olmadığından

    Sen yanlışlıkla üzerinde birleştiren bir sorgu yazamaz B.Id = B.Idyerine A.Id = B.Idkimlik alanları aynı adlı asla çünkü.

  • Daha temiz sütun isimleri.

    Adında bir sütuna bakarsanız, CustomerIdo sütunda hangi verilerin olduğunu hemen anlarsınız. Sütun adı genel bir şeye benziyorsa Id, sütunun hangi verileri içerdiğini bilmek için tablo adını da bilmeniz gerekir.

  • Gereksiz sütun takma adlarını önler

    Artık yazabilir SELECT CustomerId, ProductIdbirleştiren bir sorgudan Customersile Productsyerine,SELECT Customer.Id as CustomerId, Products.Id as ProductId

  • JOIN..USINGSözdizimine izin verir

    Tabloları Customer JOIN Products USING (CustomerId), yerine sözdizimi ile birleştirebilirsiniz .Customer JOIN Products ON Customer.Id = Products.Id

  • Anahtar aramalarda bulmak daha kolay

    Müşterinin kimliği alanını büyük bir çözümde arıyorsanız, arama yapmak arama yapmaktan CustomerIdçok daha faydalıdır.Id

Bu adlandırma kuralının başka bir avantajı olduğunu düşünürseniz, bana bildirin ve listeye ekleyeceğim.

Kimlik alanları için benzersiz veya aynı sütun adlarını kullanmayı seçmeniz size kalmış, ancak ne seçiminiz olursa olsun, lütfen tutarlı olun :)


12

Cevabımı bağlantılı sorudan kopyalamak için:

Her masaya "ID" yapıştırmanın en iyi fikir olmadığı bir durum vardır: USINGeğer destekleniyorsa , anahtar kelime. MySQL'de sıklıkla kullanıyoruz.

Örneğin, fooTablesütununda fooTableIdve barTableyabancı anahtarınız fooTableIdvarsa, sorgularınız aşağıdaki gibi oluşturulabilir:

SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)

Sadece yazmadan tasarruf etmekle kalmaz, alternatife kıyasla daha okunabilirdir:

SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)

9

Artıklığı sınırlamak için bir veritabanı şemasını normale döndürdükten sonra, tablolar kurulan ilişkilerle daha küçük tablolara bölünür (bire bir, bir çoktan çoka). İşlemde orijinal tablodaki tek alanlar birden çok normalleştirilmiş tabloda görünebilir.

Örneğin, bir blog için bir veritabanı, Author_Nickname üzerindeki benzersiz bir kısıtlama olduğu varsayılarak normal olmayan biçimde bu şekilde görünebilir.

| Author_Nickname | Author_Email | Post_Title | Post_Body |
+-----------------+--------------+------------+-----------+
| dave            | dave@x.com   | Blah       | Bla bla   |
| dave            | dave@x.com   | Stuff      | I like    |
| sophie          | s@oph.ie     | Lorem      | Ipsum     |

Normalize edilmesi iki tablo verir:

Yazar:

| Author_Nickname | Author_Email |
+-----------------+--------------+
| dave            | dave@x.com   |
| sophie          | s@oph.ie     |

İleti

| Author_Nickname | Post_Title | Post_Body |
+-----------------+------------+-----------+
| dave            | Blah       | Bla bla   |
| dave            | Stuff      | I like    |
| sophie          | Lorem      | Ipsum     |

Burada Author_Nickname, yazar tablosu için birincil anahtar ve posta tablosunda yabancı bir anahtar olacaktır. Author_Nickname iki tabloda görünse bile, yine de tek bir bilgi birimine karşılık gelir. Her sütun adı, tek bir alana karşılık gelir .

Çoğu durumda, orijinal alanlar üzerinde benzersiz bir kısıtlama olamaz, bu nedenle sayısal bir yapay alan, bunun yerine birincil anahtar olarak kullanılır. Bu, her sütun adının hala tek bir alanı temsil ettiği gerçeğini değiştirmez. Geleneksel veritabanı tasarımında, ayrı sütun adları, anahtar olmasalar bile tek alanlara karşılık gelir. (örneğin, part.name ve client.name yerine part.partname ve client.clientname kullanılır ). Bu INNER JOIN ... USING <key>ve NATURAL JOINsözdizimlerinin varlığının nedeni budur .

Bununla birlikte, günümüzde ve birçok dilde hazır bulunan ORM katmanları ile, veritabanları OO dilleri için genellikle farklı sınıflarda aynı role sahip değişkenlerin aynı olarak adlandırıldığı doğal olan kalıcı bir katman olarak tasarlanmıştır ( part.name ve client.name , part.partname ve client.clientname değil ). Böyle bir bağlamda, birincil anahtarlarım için 'ID' kullanma eğilimindeyim.


7

Bizim için bir şey oluşturmak için kiraladığımız üçüncü taraf bir satıcı, aslında tüm kimlik sütunlarını adlandırdı.

"Kimlik" yerine "Kimlik" kullanmak, "Kimlik" işlemlerinin tüm tablolarında kullanılması halinde hiçbir şeyi çözmez.

Drupal sitesindeki SQL kodlama kuralları hakkında bu durum için iyi bir uygulama olduğunu gösteren iyi bir makale var :

Olası ad alanı çakışmalarını önlemek için tablo adlarını modül adıyla öneklemek iyi bir uygulamadır.

Bu açıdan, Müşteri Ürünü ve Ajans GrubuGrup Atama'yı kullanmak mantıklı. Evet, oldukça ayrıntılı. Bunu kısaltabilirsiniz, ancak o zaman ilgilenmeniz gereken en büyük nokta, sizi izleyen geliştiricinin ne demek istediğinizi anlayabilmesi olup olmayacağıdır . Ayrıntılı tablo adlarıyla önceden tanımlanmış kimlikler, oldukları gibi belirsizlik bırakmamalıdır. Ve (benim için) bu birkaç tuş vuruşunu kaydetmekten daha önemli.


7

Sütunlarımı ID yerine Müşteri Kimliği olarak adlandırıyorum, bu yüzden ne zaman yazsam

FROM dbo.Customers AS c JOIN dbo.CustomerOrders AS o

SQL Prompt hemen aşağıdakileri önerir:

ON c.CustomerID = o.CustomerID 

Beni birkaç tuş vuruşundan kurtarıyor. Yine de adlandırma kurallarının çok öznel olduğunu ve bu nedenle bir şekilde ya da başka bir şekilde güçlü bir fikrim olmadığını düşünüyorum.


5

Tüm varchar alanlarınıza "UserText" ve "UserText1" gibi bir ad vermemenizin veya "UserDate" ve "UserDate1" kullanmamanızın nedeni aynıdır.

Tipik olarak, bir tabloda bir kimlik alanınız varsa, bu sizin birincil anahtarınızdır. Her iki tablodaki birincil anahtarın kimliği olsaydı, bir ana tabloya yabancı anahtarlı bir alt tabloyu nasıl kurardınız?

Herkes bu metodologu kabul etmiyor, fakat veritabanlarımda her tabloya benzersiz bir kısaltma yapıyorum. Bu tablo için PK, PK_ [abbrv] ID olarak adlandırılır. Eğer bir yerde FK olarak kullanılırsa, FK_ [abbrv] ID kullanırdım. Şimdi, masa ilişkilerinin ne olduğunu bulmak için sıfır tahmin çalışmam var.


5

Temelde aynı sebepten ötürü, tipik olarak, parametre 1, parametre 2 ... parametrelerini adlandırmazsınız, doğru, ancak açıklayıcı değildir. Eğer TableId'yi görürseniz, bağlamdan bağımsız olarak, Table için bir pk tutmanın kullanıldığını muhtemelen güvenle varsayabilirsiniz.

Ident'ı kimliğe her kim geldiyse, Ident ve Id kullanım kimliği arasında bir seçim yapıldığında, noktayı tamamen özlüyor. Kimlik, Id'den bile daha kafa karıştırıcı.

Bağlam dışında, Id’nin bazı tabloların birincil anahtarı olduğu varsayılabilir (kimlik bir kılavuz olmadıkça çok kullanışlı değildir), ancak Ident bile size (veya en azından bana) söylemiyor. Sonunda Ident'in kimliğe (bir şekilde veya başka bir şekilde) kısa olduğunu anlayacağım, ancak bunu anlamak için harcadığım zaman boşa gidecekti.


3

Bir önek kullanın, böylece aynı adın hem birincil anahtarda hem de yabancı anahtar bağlamlarında kullanılabilmesi için natural join/ gerçekleştirebilirsiniz join ... using.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.