Tek bir tabloda birden fazla birincil anahtar alabilir miyim?


Yanıtlar:


559

Tablo, iki veya daha fazla sütundan oluşan birincil anahtar olan Kompozit Birincil Anahtar içerebilir . Örneğin:

CREATE TABLE userdata (
  userid INT,
  userdataid INT,
  info char(200),
  primary key (userid, userdataid)
);

Güncelleme: İşte bileşik birincil anahtarların daha ayrıntılı bir açıklamasını içeren bir bağlantı .


2
Bu örnekte, benzersiz bir satırı tanımlamak / bulmak için BOTH kullanıcı kimliği ve kullanıcı verileri gerekir. OP'nin amacının ne olduğundan emin değilim, ama buraya bir anahtar kümesinden biriyle benzersiz bir şekilde bir tanımlama yapıp yapamayacağımı görmek için geldim. Örneğin, bir kullanıcı adı VEYA kullanıcı kimliği ile benzersiz bir kullanıcıyı, her ikisine de ihtiyaç duymadan tanımlamak istiyorum. Sanırım RB'nin benzersiz dizinlere cevabı orada hile yapar.
Burrito

1
@Benitok As RB. Kullanıcısının belirtilen cevap , size (aynı masada diğer benzersiz, endeksli sütunların eşsiz, endeksli sütun bağımsız) aradığınızı yapmak Benzersiz Dizinleri'ni kullanabilirsiniz. Tam olarak kullanılan dil sözdizimi ile ilgili ayrıntılar için SQL kılavuzunuza özgü lezzetinize başvurduğunuzdan emin olun.
04:00

195

Yalnızca bir birincil anahtarınız olabilir, ancak birincil anahtarınızda birden çok sütun olabilir.

Tablonuzda, benzersiz değerleri zorlayacak ve bu değerlerin sorgulanmasını hızlandıracak şekilde birincil anahtar gibi çalışacak olan Benzersiz Dizinler de olabilir.


39

Bir tablonun birden fazla aday anahtarı olabilir. Her aday anahtarı BENZERSİZ, birlikte alınan ve aynı zamanda BOŞ DEĞİL olan bir sütun veya sütun kümesidir. Bu nedenle, herhangi bir aday anahtarının tüm sütunları için değer belirtmek, ölçütleri karşılayan bir satır olduğunu veya hiç satır olmadığını belirlemek için yeterlidir.

Aday anahtarlar ilişkisel veri modelinde temel bir kavramdır.

Bir tabloda birden fazla anahtar varsa, aday anahtarlardan birini birincil anahtar olarak atamak yaygın bir uygulamadır. Tablodaki herhangi bir yabancı anahtarın, diğer herhangi bir aday anahtar yerine birincil anahtara başvurmasına neden olmak yaygın bir uygulamadır.

Bu uygulamaları tavsiye ederim, ancak ilişkisel modelde aday anahtarlar arasında birincil anahtar seçilmesini gerektiren hiçbir şey yoktur.


5
Kabul. Mantıksal modelde tüm anahtarlar eşittir (hiçbiri 'birincil' değildir). Fiziksel uygulamada hangi anahtarın PRIMARY KEY atamasını alacağı seçimi arbitray ve satıcıya / ürüne bağlıdır.
birgün

3
Veritabanı tasarımcısı bağımlı olduğunu söyleyebilirim.
Walter Mitty

Bunun gerekli olduğu bir kullanım durumuyla karşılaştım. Entity Framework tarafından oluşturulacak / yönetilecek bir tablo var - toplayabildiğim kadarıyla birincil anahtar olmayan benzersiz kompozit kısıtlamaları şu anda desteklemiyor. Ancak bileşik Birincil Anahtarları destekler. Veriler ayrıca bileşik anahtarları desteklemeyen uzak bir veritabanı sistemine de bağlanacaktır. EF'de Kompozit PK oluşturma, ancak diğer sistemin benzersiz bir şekilde tanımlamak için kullanabileceği boş olmayan bir GUID sütunu ekleyerek gittim.
Chris Nevill

2
Chris, ilişkisel modelin birincil anahtar gerektirmediğini söyledim. Bazı araçların bunları gerektirip gerektirmeyeceği hakkında hiçbir şey söylemedim. Ama anlıyorum.
Walter Mitty

Bence PK'nın asgari olması gibi bir gereklilik var, yani her kaydı benzersiz bir şekilde tanımlamak için en az sayıda sütun kullanıyor.
Gary

14

Bu hem ana sorunun hem de @ Kalmi'nin

Otomatik olarak oluşturulan birden çok sütuna sahip olmanın anlamı nedir?

Aşağıdaki kod, bileşik birincil anahtara sahiptir. Sütunlarından biri otomatik olarak artırılır. Bu yalnızca MyISAM'da çalışır. InnoDB bir hata oluşturur " HATA 1075 (42000): Hatalı tablo tanımı; yalnızca bir otomatik sütun olabilir ve bir anahtar olarak tanımlanması gerekir ".

DROP TABLE IF EXISTS `test`.`animals`;
CREATE TABLE  `test`.`animals` (
  `grp` char(30) NOT NULL,
  `id` mediumint(9) NOT NULL AUTO_INCREMENT,
  `name` char(30) NOT NULL,
  PRIMARY KEY (`grp`,`id`)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;

Which returns:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+

2
Bu, birincil anahtar tanımında önce otomatik artan sütunu belirtirseniz çalışır. (Belki bu değişti, ben sadece 5.6'da test ettim)
CTarczon

11

(Bunları çok çalışıyorum)

Aday tuşları - Bir tablo satırını benzersiz olarak tanımlamak için gereken minimum sütun birleşimi.
Bileşik tuşlar - 2 veya daha fazla sütun.

  • Bir tabloda birden fazla Aday anahtar bulunabilir.
    • Birincil anahtar - Tarafımızdan seçilen aday anahtarlardan yalnızca biri
    • Alternatif tuşlar - Diğer tüm aday anahtarlar
      • Hem Ana Anahtar hem de Alternatif anahtarlar Bileşik anahtarlar olabilir

Kaynaklar:
https://en.wikipedia.org/wiki/Superkey
https://en.wikipedia.org/wiki/Candidate_key
https://en.wikipedia.org/wiki/Primary_key
https://en.wikipedia.org / wiki / Compound_key


6

Diğerleri tarafından belirtildiği gibi, çok sütunlu birincil anahtarlara sahip olmak mümkündür. Bununla birlikte, bir anahtar tarafından kullanılmayan bazı fonksiyonel bağımlılıklarınız varsa, normalleştirmeyi düşünmelisiniz. , ilişkinizi .

Misal:

Person(id, name, email, street, zip_code, area)

A arasında fonksiyonel bir bağımlılık olabilir, id -> name,email, street, zip_code and area ancak genellikle a zip_codeile ilişkilidir areave bu nedenle arasında dahili bir fonksiyonel bağımlılık vardır.zip_code -> area .

Bu nedenle, kişi başka bir tabloya bölmeyi düşünebilir:

Person(id, name, email, street, zip_code)
Area(zip_code, name)

Böylece üçüncü normal formla tutarlıdır .


6

Birincil Anahtar, Mantıksal Model ile bağlantılı olarak "Birincil" ve bilinçaltı çağrışım nedeniyle çok talihsiz bir gösterimdir. Böylece kullanmaktan kaçınırım. Bunun yerine, Fiziksel Modelin Yedek Anahtarına ve Mantıksal Modelin Doğal Anahtarlarına başvuruyorum.

Her Varlık için Mantıksal Modelin, varlık için bir Anahtar içeren en az bir "iş özelliği" setine sahip olması önemlidir. Boyce, Codd, Date vd. İlişkisel Modelde bunlara Aday Anahtarlar olarak atıfta bulunur. Bu varlıklar için tablolar oluşturduğumuzda, Aday Anahtarları bu tablolarda Doğal Anahtar olur. Kullanıcılar yalnızca bu Doğal Anahtarlar aracılığıyla tablolardaki satırları benzersiz bir şekilde tanımlayabilir; yedek anahtarlar her zaman kullanıcılardan gizlenmelidir. Bunun nedeni, Yedek Anahtarların ticari bir anlamı olmamasıdır.

Ancak, tablolarımız için Fiziksel Model çoğu durumda Yedek Anahtar olmadan verimsiz olacaktır. Kümelenmemiş bir dizin için kapsanmayan sütunların (genel olarak) yalnızca kümelenmiş dizine Anahtar Arama yoluyla bulunabileceğini unutmayın (bir an için yığın olarak uygulanan tabloları yoksay). Mevcut Doğal Anahtar (lar) ımız geniş olduğunda, bu (1) kümelenmemiş yaprak düğümlerimizin genişliğini genişleterek depolama gereksinimlerini ve bu kümelenmemiş dizinin tarama ve taramaları için okuma erişimini artırır; ve (2) kümelenmiş endeksimizden çıkmayı azaltır, dizin yüksekliğini ve dizin boyutunu artırarak, kümelenmiş dizinlerimiz için okuma ve depolama gereksinimlerini tekrar arttırır; ve (3) kümelenmiş dizinlerimiz için önbellek gereksinimlerini artırır. diğer dizinleri ve verileri önbellekten çıkarma.

RDBMS'ye "Birincil Anahtar" olarak atanan küçük bir Yedek Anahtar burada yararlı olmaktadır. Kümeleme anahtarı olarak ayarlandığında, kümelenmemiş dizinlerden kümelenmiş dizine anahtar aramaları ve ilgili tablolardan yabancı anahtar aramaları için kullanılacak şekilde, tüm bu dezavantajlar ortadan kalkar. Kümelenmiş dizin fan çıkışlarımız, kümelenmiş dizin yüksekliğini ve boyutunu azaltmak, kümelenmiş dizinlerimiz için önbellek yükünü azaltmak, herhangi bir mekanizma yoluyla verilere erişirken (dizin taraması, dizin araması, kümelenmemiş anahtar araması veya yabancı anahtar araması) okumaları yeniden artırır tablolarımızın hem kümelenmiş hem de kümelenmemiş dizinleri için depolama gereksinimlerini azaltır.

Bu avantajların yalnızca yedek anahtar hem küçük hem de kümeleme anahtarı olduğunda ortaya çıkar. Küme anahtarı olarak bir GUID kullanılırsa, durum genellikle kullanılabilir en küçük Doğal Anahtarın kullanılmasından daha kötü olur. Tablo bir yığın olarak düzenlenmişse, 8 baytlık (yığın) RowID, 16 baytlık bir GUID'den daha iyi ancak 4 baytlık bir tam sayıdan daha az performans gösteren anahtar aramaları için kullanılır.

İş kısıtlamaları nedeniyle bir GUID kullanılması gerekiyorsa, daha iyi bir kümeleme anahtarını aramak faydalı olacaktır. Örneğin, küçük bir site tanımlayıcısı ve 4 baytlık "site-sıra numarası" mümkünse, bu tasarım Yedek Anahtar olarak bir GUID'den daha iyi performans verebilir.

Bir yığının sonuçları (belki de karma birleştirme) tercih edilen depolamayı yaparsa, daha geniş bir kümeleme anahtarının maliyetlerinin değiş tokuş analiziyle dengelenmesi gerekir.

Bu örneği düşünün ::

ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

burada " (P_Id, LastName) " dizisi benzersiz bir kısıtlama gerektirir ve uzun bir Unicode LastName artı 4 baytlık bir tamsayı olabilir ; , LastName) "ve (2) ayrı olarak küçük bir Yedek Anahtarı" Birincil Anahtar "olarak bildirir kümelenmiş bir dizinin " . Anita'nın TÜM alanlar kapsadığı için kümelenmiş bir dizinde gereksiz olan kapalı bir alanın yapılması için bu kısıtlamaya yalnızca LastName eklemek istediğini belirtmek gerekir.

SQL Server'da Birincil Anahtarı kümelenmemiş olarak atama yeteneği, "tercih edilen doğal veya aday anahtar" (Mantıksal Modelden) anlamının "Depolamada arama anahtarı" anlamıyla Fiziksel Modeli. Benim anlayış başlangıçta SYBASE SQL Server her zaman bir yığın veya kümelenmiş bir dizin içine 4-baytlık bir RowID fiziksel modelden "depolamada arama anahtarı" olarak kullandığıdır.


3
Lütfen bunu ingilizceye çevirebilir misiniz?
Jasir

3

Bazı kişiler "birincil anahtar" terimini, değerlerini bazı otomatik mekanizmalar tarafından oluşturulan tam sayı sütununu ifade etmek için kullanırlar. Örneğin AUTO_INCREMENTMySQL veyaIDENTITY Microsoft SQL Server'da. Bu anlamda birincil anahtar mı kullanıyorsunuz?

Öyleyse, cevap kullandığınız veritabanının markasına bağlıdır. MySQL'de bunu yapamazsınız, bir hata alırsınız:

mysql> create table foo (
  id int primary key auto_increment, 
  id2 int auto_increment
);
ERROR 1075 (42000): Incorrect table definition; 
there can be only one auto column and it must be defined as a key

Diğer bazı veritabanı markalarında, bir tabloda birden fazla otomatik oluşturma sütunu tanımlayabilirsiniz.


5
Otomatik olarak oluşturulan birden çok sütuna sahip olmanın anlamı nedir?
Tarnay Kálmán

Aklımda bir kullanım durumum yok, ancak herhangi bir ihtiyaç olsaydı, bazı veritabanı markaları bunu destekleyecek ve bazıları desteklemeyecekti. Tüm söylediğim bu.
Bill Karwin

1
İşte bir örnek: bir sipariş tablosunda, hem bir kimlik (otomatik artan) hem de harici bir kimlik (karma benzeri dizeler) var, her ikisi de benzersiz olmalı, bu yüzden teorik olarak her ikisinin de "birincil" olduğunu söyleyebilirsiniz. Tabii ki bu ikincil benzersiz bir endeksle yapılabilir, ancak yine de yasal bir durumdur (IMHO)
Nir

2

Aynı anda iki ana tuşa sahip olmak mümkün değildir. Ancak (davayı bileşik anahtarla karıştırmamanız durumunda), ihtiyacınız olabilecek şey bir özelliği benzersiz hale getirmektir.

CREATE t1(
c1 int NOT NULL,
c2 int NOT NULL UNIQUE,
...,
PRIMARY KEY (c1)
);

Ancak ilişkisel veritabanında bir "süper anahtar" ın, bir tablodaki bir tuple veya satırı benzersiz bir şekilde tanımlayan niteliklerin bir alt kümesi olduğunu unutmayın. 'Anahtar', anahtardan herhangi bir özniteliği kaldıran ek bir özelliğe sahip bir 'süper anahtardır', bu anahtarı artık bir 'süper anahtar' yapmaz (veya sadece bir 'anahtar' minimal bir süper anahtardır). Daha fazla anahtar varsa, hepsi aday anahtarlardır. Birincil anahtar olarak aday anahtarlarından birini seçiyoruz. Bu nedenle, tek bir ilişki veya tablo için birden çok birincil anahtardan bahsetmek bir çatışmadır.


Wikipedia'nın 'anahtar' için bir tanımı yoktur. Ayrıca "anahtardan herhangi bir özniteliğin kaldırılması, o anahtarı artık bir" süper anahtar "haline getirmez" süper anahtardan bir özniteliği kaldırırken yine de süper anahtar olabileceğinden, hiçbir şey ifade etmiyordu.
Manohar Reddy Poreddy

@ManoharReddyPoreddy Evet, bu durumda, özellik kümeniz bir 'anahtar' değil 'süper anahtar' olur. Demek istediğim, bir özellik kümesi bir 'anahtar' olacaksa, kümenin en az düzeyde olması veya kümenin, herhangi bir özniteliğin kümeden kaldırılmasının, sonuç kümesini bir 'süper anahtar' yapmamasını sağlayan ek bir özelliğe sahip olması gerekir.
Rusiru Adithya Samarasinghe

Görünüşe göre, 'anahtar' gerçek anlamınız Candidate_key ( en.wikipedia.org/wiki/Candidate_key ), belki de belirtilmelidir.
Manohar Reddy Poreddy

@ManoharReddyPoreddy Evet Cevabımda daha önce bahsetmiştim. "Eğer daha fazla anahtar varsa, hepsi aday anahtar". Her neyse, yorumunuz için teşekkürler.
Rusiru Adithya Samarasinghe

1. "Daha fazla anahtar varsa, hepsi aday anahtardır" dediğinizde, ... Aksi halde / başka bir deyişle, anahtar değil mi? ... 2. Diğer kısım nerede? ... Aynı sayfa mıyız?
Manohar Reddy Poreddy

1

Birincil anahtar, bir kaydı benzersiz şekilde tanımlayan ve tüm dizinlerde kullanılan anahtardır. Bu yüzden birden fazla olamaz. Ayrıca genellikle alt tablolara katılmak için kullanılan anahtardır, ancak bu bir zorunluluk değildir. PK'nin asıl amacı, veri değişikliklerinin doğru kaydı etkilemesi ve dizinlerin oluşturulması için bir şeyin bir kaydı benzersiz bir şekilde tanımlamanıza izin vermesini sağlamaktır.

Ancak, bir birincil anahtara (bileşik PK) birden çok alan koyabilirsiniz. Bu, birleşimlerinizi yavaşlatır (özellikle daha büyük dize türü alanlarsa) ve dizinleriniz daha büyük olur, ancak performans ve tasarım açısından bazı alt tablolarda birleşim yapma ihtiyacını ortadan kaldırabilir. davanın temeli. Bunu yaptığınızda, her alanın kendisi benzersiz değildir, ancak bunların birleşimi olur. Bileşik anahtardaki alanlardan biri veya daha fazlası da benzersizse, üzerinde benzersiz bir dizine ihtiyacınız vardır. Bir alan benzersizse, bunun PK için daha iyi bir aday olması muhtemeldir.

Şimdi zaman zaman PK için birden fazla adayınız var. Bu durumda PK olarak birini seçer veya yedek anahtar kullanırsınız (bu örnek için şahsen yedek anahtarları tercih ederim). Ve (bu kritik!) PK olarak seçilmemiş aday anahtarların her birine benzersiz dizinler eklersiniz. Verilerin benzersiz olması gerekiyorsa, PK olsun ya da olmasın benzersiz bir dizine ihtiyaç duyar. Bu bir veri bütünlüğü sorunudur. (Yedek anahtar kullandığınızda bunun da geçerli olduğunu unutmayın; insanlar yedek anahtarlarla sorun yaşarlar çünkü aday anahtarlarda benzersiz dizinler oluşturmayı unuturlar.)

Bazen birden fazla vekil anahtar istediğiniz zamanlar vardır (bunlara sahipseniz genellikle PK olur). Bu durumda istediğiniz şey daha fazla PK değil, otomatik olarak oluşturulmuş anahtarları olan alanlardır. Çoğu DB buna izin vermez, ancak bunun üstesinden gelmenin yolları vardır. İlk olarak, ikinci alanın ilk otomatik olarak oluşturulan anahtara (örneğin Alan1 * -1) göre hesaplanıp hesaplanamayacağını veya belki de ikinci bir otomatik olarak oluşturulan anahtara duyulan ihtiyacın gerçekten ilişkili bir tablo oluşturmanız gerektiği anlamına geldiğini düşünün. İlgili tablolar birebir ilişki içinde olabilir. Üst tablodan alt tabloya PK ekleyerek ve sonra tabloya yeni otomatik oluşturulan alanı ve sonra bu tablo için uygun olan alanları ekleyerek zorlarsınız. Ardından, PK olarak iki anahtardan birini seçin ve diğerine benzersiz bir dizin koyun (otomatik olarak oluşturulan alanın PK olması gerekmez). Ve FK'yi üst tablodaki alana eklediğinizden emin olun. Genel olarak, alt tablo için ek alanınız yoksa, neden iki otomatik oluşturulmuş alana ihtiyacınız olduğunu düşündüğünüzü incelemeniz gerekir.


0

İyi teknik cevaplar benden daha iyi bir şekilde verildi. Ben sadece bu konuya ekleyebilirsiniz:

İzin verilmeyen / kabul edilmeyen bir şey istiyorsanız, geri adım atmanız iyi bir nedendir.

  1. Neden kabul edilemez olmasının özünü anlayın.
  2. Belgelerde / dergi makalelerinde / web vb.
  3. Mevcut tasarımı analiz edin / gözden geçirin ve önemli kusurları gösterin.
  4. Yeni tasarım sırasında her adımı düşünün ve test edin.
  5. Her zaman dört gözle bekleyin ve uyarlanabilir bir çözüm yaratmaya çalışın.

Umarım birine yardımcı olur.


1
genel (faydalı olsa da) tavsiye, belirli bir sorunun cevabı değil.
Bradford Needham

-3

Evet, SQL'de mümkündür, ancak MsAccess'te birden fazla birincil anahtar ayarlayamayız. O zaman, diğer veritabanlarını bilmiyorum.

CREATE TABLE CHAPTER (
    BOOK_ISBN VARCHAR(50) NOT NULL,
    IDX INT NOT NULL,
    TITLE VARCHAR(100) NOT NULL,
    NUM_OF_PAGES INT,
    PRIMARY KEY (BOOK_ISBN, IDX)
);

SQL tablosunda yalnızca bir PK olabilir.
philipxy
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.