Bisakah saya memiliki beberapa kunci utama dalam satu tabel?


Jawaban:


559

Tabel dapat memiliki Kunci Utama Komposit yang merupakan kunci utama yang dibuat dari dua atau lebih kolom. Sebagai contoh:

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

Pembaruan: Berikut ini tautan dengan deskripsi yang lebih rinci tentang kunci primer komposit.


2
Dalam contoh ini, KEDUA userid dan userdataid diperlukan untuk mengidentifikasi / menemukan baris yang unik. Tidak yakin apa maksud OP itu, tetapi saya datang ke sini untuk melihat apakah saya dapat secara unik mengidentifikasi baris dengan salah satu dari serangkaian kunci. Misalnya, saya ingin mengidentifikasi pengguna unik dengan nama pengguna ATAU pengguna, tanpa perlu keduanya. Saya kira jawaban RB tentang indeks unik akan melakukan trik di sana.
Burrito

1
@ Benitok Seperti disebutkan dalam jawaban RB. , Anda dapat menggunakan Indeks Unik untuk melakukan apa yang Anda cari (kolom unik, indeks diindeks independen dari kolom unik lainnya, indeks pada tabel yang sama). Pastikan untuk berkonsultasi dengan rasa spesifik Anda tentang manual SQL untuk detail tentang sintaks bahasa yang tepat digunakan.
4AM

195

Anda hanya dapat memiliki satu kunci utama, tetapi Anda dapat memiliki beberapa kolom di kunci utama Anda.

Anda juga dapat memiliki Indeks Unik di meja Anda, yang akan bekerja sedikit seperti kunci utama karena mereka akan menegakkan nilai-nilai unik, dan akan mempercepat permintaan nilai-nilai tersebut.


39

Sebuah tabel dapat memiliki beberapa kunci kandidat. Setiap kunci kandidat adalah kolom atau kumpulan kolom yang UNIK, diambil bersama, dan juga TIDAK NULL. Dengan demikian, menentukan nilai untuk semua kolom kunci kandidat apa pun sudah cukup untuk menentukan bahwa ada satu baris yang memenuhi kriteria, atau tidak ada baris sama sekali.

Kandidat kunci adalah konsep dasar dalam model data relasional.

Ini adalah praktik umum, jika beberapa kunci ada dalam satu tabel, untuk menunjuk salah satu kunci kandidat sebagai kunci utama. Ini juga merupakan praktik umum untuk menyebabkan kunci asing ke tabel untuk referensi kunci utama, daripada kunci kandidat lainnya.

Saya merekomendasikan praktik ini, tetapi tidak ada dalam model relasional yang mengharuskan pemilihan kunci utama di antara kunci kandidat.


5
Sepakat. Semua kunci sama (tidak ada yang 'primer') dalam model logis. Pilihan kunci mana dalam implementasi fisik mendapatkan penunjukan KUNCI UTAMA adalah arbitrase dan vendor / produk tergantung.
onedaywhen

3
Saya akan mengatakan bahwa itu tergantung pada perancang basis data.
Walter Mitty

Saya baru saja menemukan kasus penggunaan di mana ini diperlukan. Saya memiliki tabel yang akan dibuat / dikelola oleh Entity Framework - yang sejauh yang saya dapat kumpulkan tidak mendukung kendala komposit unik bukan kunci utama saat ini. Namun itu mendukung Kunci Utama komposit. Data ini juga akan dihubungkan ke sistem basis data jauh yang sama sekali tidak mendukung kunci komposit. Saya telah pergi dengan membuat Composite PK di EF tetapi juga menambahkan kolom GUID yang tidak dapat dibatalkan yang sistem lain dapat gunakan untuk mengidentifikasi secara unik.
Chris Nevill

2
Chris, saya mengatakan bahwa model relasional tidak memerlukan kunci primer. Saya tidak mengatakan apa pun tentang apakah beberapa alat mungkin membutuhkannya. Tapi saya mengerti maksud Anda.
Walter Mitty

Saya pikir ada persyaratan bahwa PK minimal, yaitu, menggunakan jumlah kolom paling sedikit untuk mengidentifikasi secara unik setiap catatan.
gary

14

Ini adalah jawaban untuk pertanyaan utama dan untuk @ Kalmi tentang

Apa gunanya memiliki beberapa kolom penghasil otomatis?

Kode di bawah ini memiliki kunci primer komposit. Salah satu kolomnya bertambah otomatis. Ini hanya akan berfungsi di MyISAM. InnoDB akan menghasilkan kesalahan " ERROR 1075 (42000): Definisi tabel salah; hanya ada satu kolom otomatis dan harus didefinisikan sebagai kunci ".

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
Ini berfungsi jika Anda menentukan kolom penambahan otomatis terlebih dahulu dalam definisi kunci utama. (Mungkin ini berubah, saya baru mengujinya di 5.6)
CTarczon

11

(Sudah banyak belajar ini)

Kunci Kandidat - Kombinasi kolom minimal diperlukan untuk mengidentifikasi baris tabel secara unik.
Tombol majemuk - 2 kolom atau lebih.

  • Beberapa kunci Kandidat dapat ada dalam tabel.
    • KUNCI Utama - Hanya satu dari kunci kandidat yang dipilih oleh kami
    • Kunci alternatif - Semua kunci kandidat lainnya
      • Baik Kunci Utama & Kunci Alternatif dapat menjadi kunci majemuk

Sumber:
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

Sebagaimana dicatat oleh yang lain, dimungkinkan untuk memiliki kunci primer multi-kolom. Namun perlu dicatat bahwa jika Anda memiliki beberapa dependensi fungsional yang tidak diperkenalkan oleh kunci, Anda harus mempertimbangkan untuk menormalkan hubungan Anda.

Contoh:

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

Mungkin ada ketergantungan fungsional antara id -> name,email, street, zip_code and area Tetapi seringkali a zip_codedikaitkan dengan a areadan dengan demikian ada ketergantungan fungsional di antara zip_code -> area.

Jadi seseorang dapat mempertimbangkan untuk memecahnya menjadi tabel lain:

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

Sehingga konsisten dengan bentuk normal ketiga .


6

Primary Key adalah notasi yang sangat disayangkan, karena konotasi "Primer" dan asosiasi bawah sadar sebagai akibat dari Model Logika. Karena itu saya menghindari menggunakannya. Sebagai gantinya saya merujuk pada Kunci Pengganti dari Model Fisik dan Kunci Alami dari Model Logika.

Adalah penting bahwa Model Logika untuk setiap Entitas memiliki setidaknya satu set "atribut bisnis" yang terdiri dari Kunci untuk entitas. Boyce, Codd, Date dkk menyebut ini dalam Model Relasional sebagai Tombol Kandidat. Ketika kami kemudian membangun tabel untuk Entitas ini, Calon Kunci mereka menjadi Kunci Alami di tabel tersebut. Hanya melalui Natural Keys itulah pengguna dapat secara unik mengidentifikasi baris dalam tabel; sebagai kunci pengganti harus selalu disembunyikan dari pengguna. Ini karena Surrogate Keys tidak memiliki arti bisnis.

Namun Model Fisik untuk tabel kami dalam banyak hal akan menjadi tidak efisien tanpa Kunci Pengganti. Ingat bahwa kolom yang tidak tercakup untuk indeks yang tidak berkerumun hanya dapat ditemukan (secara umum) melalui Pencarian Kunci ke dalam indeks berkerumun (abaikan tabel yang diimplementasikan sebagai tumpukan sejenak). Ketika Natural Key kami tersedia luas, (1) memperluas lebar node daun kami, meningkatkan persyaratan penyimpanan dan membaca akses untuk mencari dan memindai indeks non-cluster; dan (2) mengurangi fan-out dari indeks berkerut kami meningkatkan tinggi indeks dan ukuran indeks, sekali lagi meningkatkan persyaratan membaca dan penyimpanan untuk indeks berkerumun kami; dan (3) meningkatkan persyaratan cache untuk indeks berkerumun kami. mengejar indeks dan data lain dari cache.

Di sinilah Kunci Pengganti kecil, yang ditunjuk untuk RDBMS sebagai "Kunci Utama" terbukti bermanfaat. Ketika ditetapkan sebagai kunci pengelompokan, sehingga dapat digunakan untuk pencarian kunci ke dalam indeks berkerumun dari indeks non-berkerumun dan pencarian kunci asing dari tabel terkait, semua kerugian ini hilang. Fan-out indeks berkerumun kami meningkat lagi untuk mengurangi tinggi dan ukuran indeks berkerumun, mengurangi beban cache untuk indeks berkerumun kami, mengurangi pembacaan saat mengakses data melalui mekanisme apa pun (apakah pemindaian indeks, pencarian indeks, pencarian kunci non-clustered atau pencarian kunci asing) dan mengurangi persyaratan penyimpanan untuk indeks berkerumun dan nonclustered dari tabel kami.

Perhatikan bahwa manfaat ini hanya terjadi ketika kunci pengganti kecil dan kunci pengelompokan. Jika GUID digunakan sebagai kunci pengelompokan, situasinya akan sering lebih buruk daripada jika Kunci Alam terkecil yang tersedia telah digunakan. Jika tabel disusun sebagai heap maka RowID 8-byte (heap) akan digunakan untuk pencarian kunci, yang lebih baik daripada GUID 16-byte tetapi lebih sedikit performanya daripada integer 4-byte.

Jika GUID harus digunakan karena kendala bisnis daripada pencarian kunci pengelompokan yang lebih baik adalah bermanfaat. Jika misalnya pengidentifikasi situs kecil dan 4-byte "situs-urutan-nomor" layak maka desain itu mungkin memberikan kinerja yang lebih baik daripada GUID sebagai Kunci Pengganti.

Jika konsekuensi dari tumpukan (hash join mungkin) menjadikan penyimpanan yang disukai maka biaya kunci pengelompokan yang lebih luas perlu diseimbangkan ke dalam analisis trade-off.

Pertimbangkan contoh ini ::

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

di mana tuple " (P_Id, LastName) " memerlukan batasan keunikan, dan mungkin Unicode LastName yang panjang ditambah bilangan bulat 4-byte, akan diinginkan untuk (1) secara tegas menegakkan batasan ini sebagai " ADD CONSTRAINT pk_PersonID UNIQUE NONCLUSTERED (P_Id , LastName) "dan (2) secara terpisah mendeklarasikan Kunci Pengganti kecil untuk menjadi" Kunci Utama "dari indeks berkerumun. Perlu dicatat bahwa Anita mungkin hanya ingin menambahkan LastName ke batasan ini untuk menjadikannya bidang tertutup, yang tidak perlu dalam indeks berkerumun karena SEMUA bidang dicakup olehnya.

Kemampuan dalam SQL Server untuk menunjuk Kunci Utama sebagai nonclustered adalah keadaan sejarah yang tidak menguntungkan, karena penyatuan makna "kunci alami atau kunci kandidat" (dari Model Logical) dengan arti "kunci pencarian dalam penyimpanan" dari Fisik Model. Pemahaman saya adalah bahwa awalnya SYBASE SQL Server selalu menggunakan RowID 4-byte, baik menjadi tumpukan atau indeks berkerumun, sebagai "kunci pencarian dalam penyimpanan" dari Model Fisik.


3
Bisakah Anda menerjemahkan ini ke bahasa Inggris!
Jasir

3

Beberapa orang menggunakan istilah "kunci utama" yang berarti kolom integer yang menghasilkan nilai-nilainya dari mekanisme otomatis. Misalnya AUTO_INCREMENTdi MySQL atau IDENTITYMicrosoft SQL Server. Apakah Anda menggunakan kunci utama dalam pengertian ini?

Jika demikian, jawabannya tergantung pada merek basis data yang Anda gunakan. Di MySQL, Anda tidak bisa melakukan ini, Anda mendapatkan kesalahan:

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 beberapa merek database lain, Anda dapat mendefinisikan lebih dari satu kolom penghasil otomatis dalam sebuah tabel.


5
Apa gunanya memiliki beberapa kolom penghasil otomatis?
Tarnay Kálmán

Saya tidak memiliki use case dalam pikiran, tetapi jika ada kebutuhan, beberapa merek database akan mendukung ini dan beberapa tidak. Itu saja yang saya katakan.
Bill Karwin

1
Berikut ini kasusnya: dalam tabel pesanan, saya memiliki ID (kenaikan otomatis) dan ID eksternal (string hash-like), keduanya harus unik sehingga secara teoritis Anda bisa mengatakan bahwa keduanya "primer". tentu saja ini dapat dilakukan dengan indeks unik sekunder tetapi masih merupakan kasus yang sah (IMHO)
Nir

2

Memiliki dua kunci utama secara bersamaan, tidak mungkin. Tapi (dengan anggapan bahwa Anda belum mengacaukan case dengan kunci komposit), mungkin yang Anda butuhkan adalah membuat satu atribut unik.

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

Namun perhatikan bahwa dalam basis data relasional 'kunci super' adalah subset atribut yang secara unik mengidentifikasi tuple atau baris dalam tabel. 'Kunci' adalah 'kunci super' yang memiliki properti tambahan yang menghapus atribut apa pun dari kunci tersebut, menjadikan kunci itu tidak lagi menjadi 'kunci super' (atau sekadar 'kunci' adalah kunci super minimal). Jika ada lebih banyak kunci, semuanya adalah kunci kandidat. Kami memilih salah satu kunci kandidat sebagai kunci utama. Itu sebabnya berbicara tentang beberapa kunci utama untuk satu relasi atau tabel menjadi konflik.


Wikipedia tidak memiliki definisi untuk 'kunci'. Juga "menghapus atribut apa pun dari kunci, membuat kunci itu tidak lebih 'kunci super'" tidak berarti apa-apa bagi saya, seperti ketika menghapus atribut dari kunci super masih bisa menjadi kunci super.
Manohar Reddy Poreddy

@ManoharReddyPoreddy Ya, dalam hal ini, set atribut Anda bukan 'kunci' tetapi 'kunci super'. Yang saya maksud adalah jika satu set atribut menjadi 'kunci', set tersebut harus minimal, atau set tersebut harus memiliki properti tambahan yang menghapus atribut apa pun dari set tersebut membuat set yang dihasilkan tidak lebih sebagai 'kunci super'.
Rusiru Adithya Samarasinghe

Sepertinya, arti sebenarnya dari 'kunci' Anda adalah Candidate_key ( en.wikipedia.org/wiki/Candidate_key ), mungkin harus disebutkan demikian.
Manohar Reddy Poreddy

@ManoharReddyPoreddy Ya saya sudah menyebutkannya dalam jawaban saya. "Jika ada lebih banyak kunci, semuanya adalah kunci kandidat". Bagaimanapun terima kasih atas ulasan Anda.
Rusiru Adithya Samarasinghe

1. Ketika Anda menyebutkan "Jika ada lebih banyak kunci, semuanya adalah kunci kandidat", ... Apakah yang Anda maksudkan sebaliknya adalah kunci kandidat? ... 2. Di mana bagian-lain? ... Apakah kita sama halaman?
Manohar Reddy Poreddy

1

Kunci utama adalah kunci yang secara unik mengidentifikasi catatan dan digunakan di semua indeks. Inilah sebabnya mengapa Anda tidak dapat memiliki lebih dari satu. Ini juga umumnya kunci yang digunakan dalam bergabung ke tabel anak tetapi ini bukan keharusan. Tujuan sebenarnya dari PK adalah untuk memastikan bahwa sesuatu memungkinkan Anda untuk mengidentifikasi secara unik catatan sehingga perubahan data memengaruhi catatan yang benar dan agar indeks dapat dibuat.

Namun, Anda bisa meletakkan beberapa bidang dalam satu kunci utama (PK komposit). Ini akan membuat sambungan Anda lebih lambat (terutama jika mereka adalah bidang tipe string yang lebih besar) dan indeks Anda lebih besar tetapi itu dapat menghapus kebutuhan untuk melakukan penggabungan di beberapa tabel anak, sejauh sejauh kinerja dan desain, bawa sebuah kasing dengan dasar kasus. Saat Anda melakukan ini, setiap bidang itu sendiri tidak unik, tetapi kombinasi keduanya. Jika satu atau lebih bidang dalam kunci komposit juga harus unik, maka Anda memerlukan indeks unik di atasnya. Sangat mungkin bahwa jika satu bidang unik, ini adalah kandidat yang lebih baik untuk PK.

Sekarang kadang-kadang, Anda memiliki lebih dari satu kandidat untuk PK. Dalam hal ini Anda memilih satu sebagai PK atau menggunakan kunci pengganti (saya pribadi lebih suka kunci pengganti untuk contoh ini). Dan (ini sangat penting!) Anda menambahkan indeks unik untuk masing-masing kunci kandidat yang tidak dipilih sebagai PK. Jika data perlu unik, perlu indeks unik apakah itu PK atau tidak. Ini adalah masalah integritas data. (Perhatikan ini juga benar setiap kali Anda menggunakan kunci pengganti; orang mendapat masalah dengan kunci pengganti karena mereka lupa membuat indeks unik pada kunci kandidat.)

Ada kalanya Anda menginginkan lebih dari satu kunci pengganti (yang biasanya PK jika Anda memilikinya). Dalam hal ini yang Anda inginkan bukan PK, lebih banyak bidang dengan kunci autogenerated. Sebagian besar DB tidak mengizinkan ini, tetapi ada cara untuk menyiasatinya. Pertama pertimbangkan apakah bidang kedua dapat dihitung berdasarkan kunci autogenerated pertama (Field1 * -1 misalnya) atau mungkin kebutuhan kunci autogenerated kedua benar-benar berarti Anda harus membuat tabel terkait. Tabel terkait dapat berada dalam hubungan satu-ke-satu. Anda akan menegakkan itu dengan menambahkan PK dari tabel induk ke tabel anak dan kemudian menambahkan bidang yang di-autogenerasi baru ke tabel dan kemudian bidang apa pun yang sesuai untuk tabel ini. Kemudian pilih salah satu dari dua kunci sebagai PK dan letakkan indeks unik di yang lain (bidang yang di-autogenerasi tidak harus menjadi PK). Dan pastikan untuk menambahkan FK ke bidang yang ada di tabel induk. Secara umum jika Anda tidak memiliki bidang tambahan untuk tabel anak, Anda perlu memeriksa mengapa Anda berpikir Anda membutuhkan dua bidang yang dibuat secara otomatis.


0

Jawaban teknis yang baik diberikan dengan cara yang lebih baik daripada yang bisa saya lakukan. Saya hanya dapat menambahkan ke topik ini:

Jika Anda menginginkan sesuatu yang tidak diperbolehkan / dapat diterima, itu adalah alasan yang baik untuk mengambil langkah mundur.

  1. Pahami inti mengapa itu tidak bisa diterima.
  2. Gali lebih dalam dokumentasi / artikel jurnal / web dan lain-lain
  3. Menganalisis / meninjau desain saat ini dan menunjukkan kelemahan utama.
  4. Pertimbangkan dan uji setiap langkah selama desain baru.
  5. Selalu melihat ke depan dan mencoba menciptakan solusi adaptif.

Semoga ini bisa membantu seseorang.


1
saran umum (meskipun bermanfaat), bukan jawaban untuk pertanyaan spesifik.
Bradford Needham

-3

Ya, ini mungkin dalam SQL, tetapi kami tidak dapat menetapkan lebih dari satu kunci utama di MsAccess. Lalu, saya tidak tahu tentang database lain.

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)
);

Tabel SQL hanya dapat memiliki satu PK.
philipxy
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.