Birden çok sütun birincil anahtarı kullanmalı mıyım yoksa yeni bir sütun mı eklemeliyim?


15

Mevcut veritabanı tasarımım, her girdiye isteğe bağlı bir anahtar atayan ek bir sütun oluşturmak yerine, varolan verileri kullanmak için birden çok sütunlu birincil anahtar kullanmaktadır (yine de benzersiz olacaktır). Buna izin verildiğini biliyorum, ancak bunun dikkatli bir şekilde kullanmak ve muhtemelen kaçınmak isteyebileceğim bir uygulama olup olmadığını merak ediyordum (C'deki goto gibi).

Peki, bu yaklaşımda görebileceğim dezavantajlardan bazıları veya tek bir sütun anahtarı istemem nedenleri nelerdir?


2
Bilmiyorum, bence bu SO'da daha iyi olurdu.
Hayal kırıklığına

2
@FrustratedWithFormsDesigner SO'ya gidebilir, ancak bence burada da işe yarıyor çünkü sorunun odak noktası "X'i nasıl yaparım?" Yerine "bu yaklaşımın artıları ve eksileri neler" gibi görünüyor.
Adam Lear

@Anna Lear ♦: Kodlama üzerinde doğrudan ve kesin bir etkisi olacak tasarım kararları ile ilgili bir "artıları ve eksileri", bu yüzden SO'nun daha iyi bir yer olacağını düşünüyorum.
FrustratedWithFormsDesigner

Yanıtlar:


8

Genellikle çok sütunlu birincil anahtarlı bir tablonuz olduğunda, kendi varlığı olarak yükseltilen (ve dolayısıyla kendi birincil anahtarını hak eden) bir birleştirme tablosunun (çoktan çoğa) sonucudur. Herhangi bir birleştirme tablosunun varsayılan olarak bir varlık olması gerektiğini iddia eden birçok kişi vardır, ancak bu başka bir gün için bir tartışmadır.

Varsayımsal olarak birçok ilişkiden varsayımlara bakalım:

Öğrenci * --- * Sınıfı

(Bir öğrenci birden fazla sınıfta olabilir, bir Sınıfın birden fazla öğrencisi olabilir).

Bu iki tablo arasında StudentClass (ya da nasıl yazdığınıza bağlı olarak ClassStudent) adı verilen bir bağlantı tablosu olacaktır. Bazen, öğrencinin sınıftayken olduğu gibi şeyleri takip etmek istersiniz. Böylece StudentClass tablosuna ekleyeceksiniz. Bu noktada, StudentClass benzersiz bir varlık haline gelmiştir ... ve bu adı tanıması için bir isim verilmelidir, örneğin Kayıt.

Öğrenci 1 --- * Kayıt * --- 1 Sınıf

(bir öğrencinin birden fazla Kaydı olabilir, her Kayıt bir sınıf içindir (veya bir Sınıfın birçok Kaydı olabileceğinin tersi, her Kayıt bir Öğrenci içindir).

Şimdi geçtiğimiz yıl Kimya 101 dersine kaç öğrenci kaydolduğu gibi şeyleri sorgulayabilirsiniz? Ya da John Doe öğrencisi Acme Üniversitesi'ne devam ederken hangi derslere kaydoldu? Bu, ayrı birincil anahtar olmadan mümkün oldu, ancak kayıt için birincil anahtarınız olduğunda, bu kayıtlardan daha kolay bir sorgu olabilir (kimliğe göre), kaç öğrenci geçer not aldı?

Bir varlığın bir PK'yi hak edip etmediğini belirleme, o varlık için ne kadar sorgulama (veya manipülasyon) yapacağınızla ilgilidir. Diyelim ki, bir sınıftaki bir öğrenci için tamamlanan ödevleri eklemek istediniz. Bu varlığı (Atama) iliştirmek için mantıklı yer Kayıt Kuruluşunda olacaktır. Kaydı kendi birincil anahtarı vermek Ödev sorgularını basitleştirecektir.


1
Böylece StudentClass tablosuna ekleyeceksiniz. Bu noktada, StudentClass benzersiz bir varlık haline gelmiştir ... ve bu adı tanıması için bir isim verilmelidir, örneğin Kayıt. Bu çok basit bir şey, ama bunu yapmanın çok büyük bir değeri var!
Botis

8

Ayrı bir kimlik sütununa sahip olmak mantıklıdır. Veritabanı tablonuzdan bir şey almak istediğinizde, bunu yapmak daha kolaydır:

SELECT whatever FROM table WHERE id=13

tablodan NEREDEN SEÇ, NEREDE col1 = 'val1' VE col2 = 'val2' VE col3 = 'val3'

Örneğin, bir web uygulamasında şöyle görünen bir URL'ye dönüşür:

www.somewebsite.com/somepage.php?id=13

ya da bunun gibi:

www.somewebsite.com/somepage.php?col1=val1&col2=val2&col3=val3

4
Ve birkaç sütun yerine bir
kimliğe bağlantı kurabildiğinizde

3
Üzgünüm, bu noktada -1'e ihtiyacım var, çünkü A) siyah ve beyaz değil. Kimlik sütunu eklemek, bu yeni kimliği nerede ve ne zaman oluşturduğunuz gibi negatiflerle birlikte gelir. Ayrıca, fazladan eklemelere veya SELECTsorgulara neden olabilir . Ve B) , bunun aslında herhangi bir URL gereksinimine nasıl neden olduğu hakkında hiçbir fikrim yok (kötü bir çerçeveyle çalışmadığınız sürece). URL'lerimde ?id=13, içinde bırakılmak üzere hiçbir sorgu dizesi yok ?col1=val1&col2=val2&col3=val3.
Nicole

2
@renesis: Bu sitede URL'lerde bulunan benzersiz sorular ve kullanıcılar var. Bununla birlikte, bu özel bir durumdur, çünkü bu belirli veriler değişmez.
Michael K

1
@Renesis, çoğu (belki de hepsi) modern db'lerin kimliği otomatik ve güvenli bir şekilde oluşturabilen ve bunları sql sorgusu veya kütüphane işlev çağrısı ile raporlayabilen auto_increment tamsayı sütun türlerine sahiptir. Veya dağıtılmış bir ortamda, büyük bir rasgele karma kullanırsınız. Tabloda zaten bir tane yoksa , bazı DB'ler sizin için gizli bir kimlik sütunu bile oluşturacaktır .
GrandmasterB

@Michael - Kimliklerin asla URL'lerde olmadığını söylemedim. Tabii ki öyleler. Bir veri satırını temsil eden URL'leriniz varsa, evet, bu verilerin muhtemelen benzersiz bir kimliği olmalıdır. URL'nin başka bir kısmı zaten çoklu anahtarın diğer kısımlarını sağlamadığı sürece. @GrandmasterB Her ikisi de MySQL (biri Oracle ve SQL Server'ı da destekliyor) kullanan son iki şirketten (6 yılı aşkın bir süredir) otomatik artış veya büyük bir rasgele karma kullanamadık.
Nicole

8

Temel olarak vekil mi yoksa doğal anahtarlar mı kullanmanız gerektiğini soruyorsunuz (sizin durumunuzda bileşik doğal anahtarlar gibi geliyor ). İşte harika bir makale: http://www.agiledata.org/essays/keys.html

Yedek anahtarları tercih ediyorum çünkü DB'nin ömrü boyunca yönetimi basitleştiriyorlar (anahtarların anlamını değiştirmekten asla endişelenmenize gerek yok, bu asla olmamalı, ancak insanların dahil olduğu herhangi bir gerçek sistemde yok). Ancak , DB'de "temelde anahtar: değer çiftleri olan" çok fazla "arama" tablosu varsa, anlamlı sonuçlar elde etmek için bu tabloları sorguya birleştirmeniz gerektiğinden yedek anahtarlar hantal olabilir.

Örneğin, iki varlığınız olduğunu varsayalım: Adres ve Ülke.

  • İlişki: Adres * ----- 1 Ülke
  • Ülke kuruluşu temelde bir anahtar: değer çiftidir (ör. ABD: ABD, CA: Kanada, MX: Meksika vb.)
  • Bu yapıyı ABD'deki tüm Adresler için sorgulamak için:

select * from Address where CountryCode = 'US'

  • Yedek anahtarlarla aynı sorguyu gerçekleştirmek için:

select Address.* from Address join Country on Address.CountryID = Country.ID where Country.Code = 'US'

Doğal anahtarların çok sık değişmeyeceğinden eminsem, arama tabloları için doğal anahtarları ve her şey için yedek anahtarları zorunlu kılıyorum.


5

Verilere nasıl eriştiğinize bağlıdır. Çok sayıda kısmi tuş araması yaparsanız (üç tuştan sadece ikisini temel alarak kayıtları seçtiğinizde), çok parçalı tuşları saklamak istersiniz. OTOH, diğer tablolarla çok fazla 1: 1 ilişkiniz varsa, bir yedek anahtar olması muhtemelen daha mantıklıdır.


1

Her tablo için her zaman vekil birincil anahtar bulundurmayı seviyorum. Ama bunu duymak için zor bir neden yok.

Çok sütunlu bir doğal anahtar beni ısırdığımda bir kez ORM ile oldu. Bazen Linq To Entities kullanarak bir çoklu sütun birincil anahtar ile sorunları olurdu.


1

Asla asla deme, ama 4 sütuna katılmak acı vericidir. Akıllı verilerle ne kadar çok sütununuz varsa, bu değerlerin değişme şansı o kadar artar. Veritabanları basamaklı güncellemelerle referans bütünlüğünü korumak için ayarlanabilir.

Benzersiz değerleri işlemek için her zaman başka bir dizin oluşturabilirsiniz.

Performans çoğu durumda göz ardı edilebilir, ancak sorgularınızı ayrı anahtarla veya anahtarsız olarak test edebilirsiniz.


0

Ayrı bir anahtarı zorunlu kılmak için iyi bir neden bulmakta zorlanıyorum, ama dediğin gibi birçok kişi bunu koydu.

Aslında / detay tabloları ile uğraşırken yardım (özellikle depolama ile) bulamıyorum. Kanonik örnek (customer_key, store_key, Product_Key) ile bir satış özellik tablosu miktarı rekor düzey anahtara sahip çok mantıklı değil.


0

Kompozit anahtarınızın gerçekte kopyaları olabileceğini fark ederseniz, PK'nin otomatik bir entrement int olması zorluğu azaltır.


0

Ask Tom hakkında 2002 yılına kadar iyi bir tartışma var . Oracle'a özgüdür, ancak daha geniş tartışma hangi veritabanını kullanırsanız kullanın.

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.