Bisakah kunci asing berupa NULL dan / atau duplikat?

325

Tolong jelaskan dua hal untuk saya:

  1. Bisakah kunci asing menjadi NULL?
  2. Bisakah kunci asing digandakan?

Seadil yang saya tahu, NULLtidak boleh digunakan dalam kunci asing, tetapi dalam beberapa aplikasi saya, saya dapat memasukkan NULLOracle dan SQL Server, dan saya tidak tahu mengapa.

selai
sumber
1
@Adrian: Yang terbaik dari pengetahuan saya kunci asing tidak boleh nol tetapi mengambil null di sql server dan oracle. dapatkah Anda menjelaskan mengapa?
selai
@ Jam - baca tautan di jawaban saya.
JNK
11
ini tidak dapat dihapus karena jawaban dan pertanyaannya berguna. Silakan mengedit pertanyaan untuk memperbaikinya.
Jeff Atwood
Silakan pisahkan pertanyaan tentang duplikat. Hanya satu tentang NULL yang dijawab di bawah ini.
reinierpost

Jawaban:

529

Jawaban singkat: Ya, bisa NULL atau duplikat.

Saya ingin menjelaskan mengapa kunci asing mungkin harus nol atau mungkin harus unik atau tidak unik. Pertama-tama ingat kunci Asing hanya mensyaratkan bahwa nilai dalam bidang itu harus ada terlebih dahulu di tabel yang berbeda (tabel induk). Itu semua adalah definisi FK. Null menurut definisi bukan nilai. Null berarti kita belum tahu nilainya.

Biarkan saya memberi Anda contoh kehidupan nyata. Misalkan Anda memiliki database yang menyimpan proposal penjualan. Anggap lebih jauh bahwa setiap proposal hanya memiliki satu tenaga penjualan yang ditugaskan dan satu klien. Jadi tabel proposal Anda akan memiliki dua kunci asing, satu dengan ID klien dan satu dengan ID staf penjualan. Namun, pada saat catatan dibuat, seorang tenaga penjualan tidak selalu ditugaskan (karena belum ada yang bebas untuk mengerjakannya), sehingga ID klien diisi tetapi ID tenaga penjualan mungkin nol. Dengan kata lain, biasanya Anda membutuhkan kemampuan untuk memiliki null FK ketika Anda mungkin tidak tahu nilainya pada saat data dimasukkan, tetapi Anda tahu nilai-nilai lain dalam tabel yang perlu dimasukkan. Untuk mengizinkan nol di FK umumnya yang harus Anda lakukan adalah mengizinkan nol di bidang yang memiliki FK. Nilai nol terpisah dari ide menjadi FK.

Apakah itu unik atau tidak unik berkaitan dengan apakah tabel memiliki hubungan satu-satu atau banyak-ke tabel induk. Sekarang jika Anda memiliki hubungan satu-satu, ada kemungkinan bahwa Anda dapat memiliki semua data dalam satu tabel, tetapi jika tabel menjadi terlalu luas atau jika data berada pada topik yang berbeda (karyawan - contoh asuransi @tbone memberi misalnya), maka Anda ingin tabel terpisah dengan FK. Anda kemudian ingin membuat FK ini juga sebagai PK (yang menjamin keunikan) atau menempatkan batasan unik di atasnya.

Sebagian besar FK adalah untuk hubungan satu ke banyak dan itulah yang Anda dapatkan dari FK tanpa menambah kendala lebih lanjut di lapangan. Jadi, Anda memiliki tabel pesanan dan tabel detail pesanan misalnya. Jika pelanggan memesan sepuluh item sekaligus, ia memiliki satu pesanan dan sepuluh catatan detail pesanan yang berisi ID pemesanan yang sama dengan FK.

HLGEM
sumber
13
Jadi itu dimaksudkan untuk menjadi lebih baik daripada memiliki orang penjualan palsu bernama "Tidak Ditugaskan"?
Thomas Weller
8
Komentar. Nulls meninggalkan banyak ruang untuk kesalahan dalam kueri oleh orang-orang yang tidak tahu bagaimana SQL (mis) menangani 3VL. Jika seorang tenaga penjualan benar-benar tidak diperlukan untuk tabel-r tertentu, hanya saja Anda tidak memasukkan catatan itu. Tabel terpisah dapat "ProposalAssignedTo" atau semacamnya, dengan batasan yang sesuai. Seorang penulis kueri kemudian dapat bergabung ke tabel itu, dan memberikan logika mereka sendiri untuk apa pun yang ingin kita lakukan ketika proposal tidak memiliki tenaga penjual. NULL tidak hanya berarti "kita tidak tahu" - itu dapat digunakan untuk banyak hal (itulah sebabnya hampir selalu merupakan ide yang buruk)
N West
26
@nWest, saya tidak mengizinkan orang yang tidak kompeten untuk menanyakan database saya dan pengembang yang tidak tahu bagaimana menangani null tidak kompeten. Ada kalanya data tidak diketahui pada saat entri data awal untuk bidang tertentu tetapi bidang lainnya diperlukan pada saat itu.
HLGEM
28
@ThomasWeller Merujuk wiraniaga palsu ("Tidak Ditugaskan") membuat masalahnya menjadi lebih buruk. Saya menganggap tabel tenaga penjual Anda memiliki beberapa kolom ...? Berapa nomor asuransi sosial Tn. Unassigned? Departemen mana dia ditugaskan? Siapa bosnya? Saya harap Anda mengerti maksud saya: ketika Anda membuat tenaga penjual "Tidak Ditugaskan", Anda dengan cepat menemukan bahwa Anda berdagang NULLdi satu meja dengan beberapa NULLs di tabel yang berbeda.
Gili
1
@ ThomasWeller Anda juga akan memiliki masalah jika / ketika Anda perlu melokalisasi antarmuka Anda.
tobiv
50

1 - Ya, setidaknya SQL Server 2000.

2 - Ya, selama itu bukan UNIQUEkendala atau tertaut ke indeks unik.

JNK
sumber
Tautan itu sudah mati.
MikeTheLiar
45

Dari mulut kuda:

Kunci asing memungkinkan nilai kunci yang semuanya NULL, bahkan jika tidak ada kunci PRIMARY atau UNIK yang cocok

Tidak Ada Kendala pada Kunci Asing

Ketika tidak ada batasan lain yang didefinisikan pada kunci asing, sejumlah baris dalam tabel anak dapat referensi nilai kunci induk yang sama. Model ini memungkinkan nulls di kunci asing. ...

BUKAN NULL Kendala pada Kunci Asing

Ketika nol tidak diizinkan di kunci asing, setiap baris dalam tabel anak harus secara eksplisit merujuk nilai pada kunci induk karena nol tidak diizinkan di kunci asing.

Sejumlah baris dalam tabel anak dapat merujuk nilai kunci induk yang sama, sehingga model ini membangun hubungan satu-ke-banyak antara induk dan kunci asing. Namun, setiap baris dalam tabel anak harus memiliki referensi ke nilai kunci induk; tidak adanya nilai (nol) di kunci asing tidak diperbolehkan. Contoh yang sama pada bagian sebelumnya dapat digunakan untuk menggambarkan hubungan seperti itu. Namun, dalam hal ini, karyawan harus memiliki referensi ke departemen tertentu.

Batasan UNIK tentang Kunci Asing

Ketika batasan UNIK didefinisikan pada kunci asing, hanya satu baris dalam tabel anak dapat referensi nilai kunci induk yang diberikan. Model ini memungkinkan nulls di kunci asing.

Model ini membangun hubungan satu-ke-satu antara induk dan kunci asing yang memungkinkan nilai yang tidak ditentukan (nol) di kunci asing. Misalnya, asumsikan bahwa tabel karyawan memiliki kolom bernama MEMBERNO, merujuk pada nomor keanggotaan karyawan dalam rencana asuransi perusahaan. Juga, sebuah tabel bernama ASURANSI memiliki kunci utama bernama MEMBERNO, dan kolom lain dari tabel tersebut menyimpan informasi masing-masing yang berkaitan dengan polis asuransi karyawan. MEMBERNO dalam tabel karyawan harus berupa kunci asing dan kunci unik:

  • Untuk memberlakukan aturan integritas referensial antara tabel EMP_TAB dan ASURANSI (batasan FOREIGN KEY)

  • Untuk menjamin bahwa setiap karyawan memiliki nomor keanggotaan yang unik (batasan utama UNIQUE)

Batasan UNIK dan BUKAN NULL pada Kunci Asing

Ketika batasan UNIQUE dan NOT NULL didefinisikan pada kunci asing, hanya satu baris dalam tabel anak yang dapat mereferensikan nilai kunci induk yang diberikan, dan karena nilai-nilai NULL tidak diperbolehkan dalam kunci asing, setiap baris dalam tabel anak harus secara eksplisit merujuk nilai pada kunci induk.

Lihat ini:

Tautan Oracle 11g

tulang T
sumber
16

Ya kunci asing bisa nol seperti yang dikatakan di atas oleh programmer senior ... Saya akan menambahkan skenario lain di mana kunci Asing akan diminta menjadi nol .... misalkan kita memiliki tabel komentar, Gambar dan Video dalam aplikasi yang memungkinkan komentar pada gambar dan video. Dalam tabel komentar kita dapat memiliki dua PicturesId Kunci Asing, dan VideosId bersama dengan CommentId Kunci utama. Jadi ketika Anda mengomentari video, hanya VideosId yang diperlukan dan pictureId akan menjadi nol ... dan jika Anda mengomentari gambar, hanya PictureId yang diperlukan dan VideosId akan menjadi nol ...

Touseef Ahmed Awan
sumber
1
Saya pikir ada cara yang lebih baik untuk menyelesaikan masalah ini. Daripada membuat kolom baru, Anda dapat memiliki dua kolom, yaitu "id" dan "ketik", yang akan berisi id dan nama tabel kunci asing. Misalnya, id = 1, tipe = Gambar akan mewakili tautan ke tabel Gambar dengan id 1. Keuntungan menggunakan solusi ini adalah, Anda tidak perlu membuat kolom baru ketika komentar ditambahkan ke tabel tambahan. Kerugian tidak akan ada batasan kunci asing pada tingkat db, melainkan kendala harus tingkat aplikasi.
Agent47DarkSoul
4
@ Agent: Kami sudah memiliki "solusi" ini dalam penggunaan produksi. Jangan lakukan itu, itu mengerikan. Membuat pertanyaan menjadi kekacauan ini, "jika ini tipe 1, gabung ke tabel ini, jika tidak gabung ke ini" Itu adalah mimpi buruk bagi kami. Kami akhirnya melakukan apa yang dikatakan jawaban ini dan membuat kolom baru untuk setiap jenis bergabung. Membuat kolom itu murah. Cukup banyak itu hanya cacat adalah bahwa banyak kolom membuat Toad sulit digunakan, tapi itu hanya cacat Toad.
user128216
1
@FighterJet Rails menyediakan kerangka kerja ORM yang hebat yang menangani bahkan pertanyaan kompleks dengan solusi ini.
Agent47DarkSoul
2
@ Agent: Mungkin bisa ... tetapi jika Anda bisa membuatnya sederhana, mengapa membuatnya rumit? Dan mungkin "mimpi buruk" adalah kata yang salah untuk digunakan: itu hanya sangat tidak nyaman. Kami tidak menderita masalah integritas data (banyak).
user128216
7

itu tergantung pada peran apa yang foreign keydimainkannya dalam hubungan Anda.

  1. apakah ini foreign keyjuga akey attribute dalam hubungan Anda, maka itu tidak bisa NULL
  2. jika ini foreign keyadalah atribut normal dalam relasi Anda, maka itu bisa NULL.
Shinxg
sumber
3

Berikut ini contoh menggunakan sintaks Oracle:
Pertama mari kita buat tabel COUNTRY

CREATE TABLE TBL_COUNTRY ( COUNTRY_ID VARCHAR2 (50) NOT NULL ) ;
ALTER TABLE TBL_COUNTRY ADD CONSTRAINT COUNTRY_PK PRIMARY KEY ( COUNTRY_ID ) ;

Buat tabel PROVINCE

CREATE TABLE TBL_PROVINCE(
PROVINCE_ID VARCHAR2 (50) NOT NULL ,
COUNTRY_ID  VARCHAR2 (50)
);
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_PK PRIMARY KEY ( PROVINCE_ID ) ;
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_COUNTRY_FK FOREIGN KEY ( COUNTRY_ID ) REFERENCES TBL_COUNTRY ( COUNTRY_ID ) ;

Ini berjalan dengan baik di Oracle. Perhatikan kunci asing COUNTRY_ID di tabel kedua tidak memiliki "NOT NULL".

Sekarang untuk menyisipkan baris ke dalam tabel PROVINCE, cukup untuk menentukan PROVINCE_ID saja. Namun, jika Anda memilih untuk menentukan COUNTRY_ID juga, itu harus sudah ada di tabel COUNTRY.

Mouhcine
sumber
1

Secara default tidak ada batasan pada kunci asing, kunci asing dapat menjadi nol dan duplikat.

saat membuat tabel / mengubah tabel, jika Anda menambahkan batasan keunikan atau bukan nol maka hanya itu yang tidak akan memungkinkan nilai null / duplikat.

nitin lalwani
sumber
0

Sederhananya, hubungan "Tidak Mengidentifikasi" antara Entitas adalah bagian dari ER-Model dan tersedia di Microsoft Visio ketika merancang ER-Diagram. Ini diperlukan untuk menegakkan kardinalitas antara Entitas tipe "nol atau lebih dari nol", atau "nol atau satu". Catat "nol" ini dalam kardinalitas alih-alih "satu" dalam "satu ke banyak".

Sekarang, contoh hubungan non-identifikasi di mana kardinalitas mungkin "nol" (non-mengidentifikasi) adalah ketika kita mengatakan catatan / objek dalam satu entitas-A "mungkin" atau "mungkin tidak" memiliki nilai sebagai referensi ke catatan / s di Entitas lain-B.

Seperti, ada kemungkinan untuk satu catatan entitas-A untuk mengidentifikasi dirinya dengan catatan Entitas-B lainnya, oleh karena itu harus ada kolom di Entitas-B untuk memiliki nilai identitas dari catatan Entitas-B. Kolom ini mungkin "Null" jika tidak ada catatan di Entity-A mengidentifikasi rekaman / s (atau, objek / s) di Entity-B.

Dalam Paradigma Berorientasi Objek (dunia nyata), ada situasi ketika objek Kelas-B tidak selalu bergantung (sangat berpasangan) pada objek kelas-A untuk keberadaannya, yang berarti Kelas-B secara longgar digabungkan dengan Kelas- A sedemikian sehingga Kelas-A dapat "Mengandung" (Containment) objek Kelas-A, yang bertentangan dengan konsep objek Kelas-B harus memiliki (Komposisi) objek Kelas-A, untuk (objek kelas-nya) B) penciptaan.

Dari sudut pandang SQL Query, Anda bisa meminta semua catatan dalam entitas-B yang "tidak nol" untuk kunci asing yang disediakan untuk Entity-B. Ini akan membawa semua catatan yang memiliki nilai tertentu yang sesuai untuk baris di Entity-A atau semua catatan dengan nilai Null akan menjadi catatan yang tidak memiliki catatan apa pun di Entity-A di Entity-B.

Fakhar
sumber
-1

Saya pikir lebih baik mempertimbangkan kemungkinan kardinalitas yang kita miliki di tabel. Kita dapat memiliki kardinalitas minimum nol. Ketika itu opsional, partisipasi minimum tupel dari tabel terkait bisa nol, Sekarang Anda menghadapi keharusan nilai kunci asing diizinkan nol.

Tetapi jawabannya adalah itu semua tergantung pada Bisnis.

pengguna9274383
sumber
-3

Gagasan kunci asing didasarkan pada konsep referensi nilai yang sudah ada di tabel utama. Itu sebabnya disebut kunci asing di tabel lain. Konsep ini disebut integritas referensial. Jika kunci asing dinyatakan sebagai bidang nol, itu akan melanggar logika integritas referensial. Apa yang dimaksud? Itu hanya bisa merujuk ke sesuatu yang ada di tabel utama. Oleh karena itu, saya pikir akan salah untuk menyatakan bidang kunci asing sebagai nol.

SQLDev
sumber
Itu dapat merujuk "tidak ada" atau Anda belum tahu nilainya NULL, tetapi apa yang dikatakan integritas referensial adalah bahwa jika referensi "sesuatu" itu harus ada di sana.
Yaxe
-7

Saya pikir kunci asing dari satu tabel juga kunci utama ke beberapa tabel lainnya. Jadi itu tidak akan mengizinkan nulls.Jadi tidak ada pertanyaan tentang memiliki nilai nol dalam kunci asing.

pengguna4532553
sumber