Penggunaan beberapa kunci asing pada kolom yang sama di SQL Server

10

SQL Server memungkinkan saya untuk membuat beberapa kunci asing pada kolom, dan setiap kali menggunakan nama yang berbeda saya dapat membuat referensi kunci lain ke objek yang sama. Pada dasarnya semua kunci mendefinisikan hubungan yang sama. Saya ingin tahu apa gunanya memiliki beberapa kunci asing yang didefinisikan pada kolom yang sama dan referensi ke kolom yang sama di tabel lain. Apa manfaatnya sehingga SQL Server memungkinkan kita melakukan hal seperti itu?

masukkan deskripsi gambar di sini

igelr
sumber

Jawaban:

12

Tidak ada untungnya memiliki kendala yang berlebihan yang hanya berbeda berdasarkan nama. Demikian pula, tidak ada manfaatnya memiliki indeks berlebihan yang hanya berbeda berdasarkan nama. Keduanya menambah overhead tanpa nilai.

Mesin database SQL Server tidak menghentikan Anda dari melakukannya. Konvensi penamaan kendala penamaan yang baik (misalnya FK_ReferencingTable_ReferencedTable) dapat membantu melindungi salah satunya dari kesalahan tersebut.

Dan Guzman
sumber
17

SQL Server memungkinkan Anda melakukan banyak hal konyol.

Anda bahkan dapat membuat kunci asing pada kolom yang mereferensikan sendiri - terlepas dari kenyataan bahwa ini tidak akan pernah bisa dilanggar karena setiap baris akan menemui kendala pada dirinya sendiri.

Satu kasus tepi di mana kemampuan untuk membuat dua kunci asing pada hubungan yang sama akan berpotensi bermanfaat adalah karena indeks yang digunakan untuk memvalidasi kunci asing ditentukan pada waktu pembuatan. Jika indeks yang lebih baik (yaitu lebih sempit) muncul kemudian maka ini akan memungkinkan batasan kunci asing baru dibuat terikat pada indeks yang lebih baik dan kemudian kendala asli turun tanpa ada celah tanpa kendala aktif.

(Seperti dalam contoh di bawah ini)

CREATE TABLE T1(
    T1_Id INT PRIMARY KEY CLUSTERED  NOT NULL,
    Filler CHAR(4000) NULL,
) 

INSERT INTO T1 VALUES (1, '');

CREATE TABLE T2(
    T2_Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
    T1_Id INT NOT NULL CONSTRAINT FK REFERENCES T1 (T1_Id), 
    Filler CHAR(4000) NULL,
)


ALTER TABLE T1 ADD CONSTRAINT
    UQ_T1 UNIQUE NONCLUSTERED(T1_Id) 


/*Execution Plan uses clustered index*/ 
INSERT INTO T2 VALUES (1,1) 

ALTER TABLE T2  WITH CHECK ADD  CONSTRAINT FK2 FOREIGN KEY(T1_Id)
REFERENCES T1 (T1_Id)    

ALTER TABLE T2 DROP CONSTRAINT FK

/*Now Execution Plan now uses non clustered index*/    
INSERT INTO T2 VALUES (1,1)    

DROP TABLE  T2, T1;

Sebagai tambahan untuk periode sementara sementara kedua kendala ada setiap sisipan akhirnya divalidasi terhadap kedua indeks.

Martin Smith
sumber
Bisakah transaksi digunakan untuk memastikan pembaruan kendala tanpa celah yang sama? Apakah metode non-transaksi ini lebih baik karena kurang mengunci, mungkin?
binki
13

Tidak ada gunanya memiliki batasan kunci asing yang identik., Yaitu pada kolom yang sama dan referensi tabel dan kolom yang sama.

Ini seperti memiliki cek yang sama 2 kali atau lebih.

ypercubeᵀᴹ
sumber
-Tidak setuju. Mungkin ada kemungkinan bahwa tabel primer membutuhkan dua pemeriksaan terpisah. Lihat contoh di bawah ini pengirim dan penerima sama sekali berbeda - stackoverflow.com/questions/40400483/…
trex
@trex Anda berbicara tentang sesuatu yang berbeda. Pertanyaannya di sini menyatakan: "Saya ingin tahu apa gunanya memiliki beberapa kunci asing yang didefinisikan pada kolom yang sama dan merujuk ke kolom yang sama di tabel lain ."
ypercubeᵀᴹ
@ ypercubeᵀᴹ - Mengerti. Terima kasih telah menjelaskannya
trex
6

Alasan yang sama Anda dapat membuat 50 indeks pada kolom yang sama, menambahkan file log kedua, mengatur memori server maks ke 20MB ... kebanyakan orang tidak akan melakukan hal-hal ini, tetapi mungkin ada alasan yang sah untuk melakukannya kadang-kadang, jadi tidak ada manfaat dalam menciptakan overhead di mesin untuk menambah pemeriksaan terhadap hal-hal yang hanya keliru.

Aaron Bertrand
sumber
2

Kedengarannya seperti hal biru-hijau.

Ketika Anda mulai berpindah dari biru ke hijau, Anda perlu sementara membuat salinan barang.

Yang ingin kami lakukan adalah sementara membuat kunci asing tambahan CHECK WITH NOCHECKdan ON UPDATE CASCADE ON DELETE SET NULL; apa yang dilakukan adalah kunci asing yang berfungsi tetapi baris yang ada tidak dicentang saat kunci dibuat.

Kemudian setelah membersihkan semua baris yang harus cocok, kami akan membuat kunci asing baru tanpa opsi perintah (default adalah CHECK WITH CHECKyang biasanya Anda inginkan), dan menjatuhkan kunci asing sementara.

Perhatikan bahwa jika Anda baru saja menjatuhkan dan membuat ulang kunci asing, beberapa baris sampah bisa lewat begitu saja.

Joshua
sumber