Saya memiliki sebuah tabel di mana baris-baris tersebut dapat saling berhubungan satu sama lain, dan secara logis, hubungan berjalan dua arah (pada dasarnya, tanpa arah) antara dua baris. (Dan jika Anda bertanya-tanya, ya, ini benar-benar harus menjadi satu tabel. Ini adalah dua hal dari entitas / tipe logis yang sama persis.) Saya dapat memikirkan beberapa cara untuk mewakili ini:
- Simpan hubungan dan kebalikannya
- Menyimpan hubungan satu arah, membatasi database agar tidak menyimpannya dengan cara lain, dan memiliki dua indeks dengan pesanan berlawanan untuk FK (satu indeks menjadi indeks PK)
- Simpan hubungan satu arah dengan dua indeks dan biarkan yang kedua tetap dimasukkan (kedengarannya agak menjijikkan, tapi hei, kelengkapan)
- Buat semacam tabel pengelompokan dan minta sebuah FK di atas meja asli untuk itu. (Meningkatkan banyak pertanyaan. Tabel pengelompokan hanya akan memiliki nomor; mengapa bahkan memiliki tabel? Membuat FK NULLable atau memiliki grup dengan satu baris yang terkait?)
Apa saja pro dan kontra utama dari cara-cara ini, dan tentu saja, adakah cara yang belum saya pikirkan?
Inilah SQLFiddle untuk dimainkan: http://sqlfiddle.com/#!12/7ee1a/1/0 . (Terjadi menjadi PostgreSQL karena itulah yang saya gunakan, tetapi saya tidak berpikir pertanyaan ini sangat spesifik untuk PostgreSQL.) Saat ini menyimpan hubungan dan membalikkannya hanya sebagai contoh.
sumber
Jawaban:
Apa yang Anda rancang bagus. Apa yang perlu ditambahkan adalah kendala untuk membuat hubungan tanpa arah. Jadi, Anda tidak dapat memiliki
(1,5)
baris tanpa(5,1)
menambahkan baris juga.Ini dapat dilakukan * dengan batasan referensi diri di tabel jembatan.
*: dapat diselesaikan di Postgres, Oracle, DB2, dan semua DBMS yang telah menerapkan batasan kunci asing seperti yang dijelaskan oleh standar SQL (ditangguhkan, mis. diperiksa pada akhir transaksi.) Pemeriksaan yang ditangguhkan sebenarnya tidak diperlukan, seperti pada SQL- Server yang memeriksa mereka di akhir pernyataan dan konstruksi ini masih berfungsi. Anda tidak dapat melakukan ini di MySQL karena "InnoDB memeriksa batasan UNIQUE dan FOREIGN KEY baris-demi-baris" .
Jadi, di Postgres berikut ini akan sesuai dengan kebutuhan Anda:
Diuji di: SQL-Fiddle
Jika Anda mencoba menambahkan baris
(1,5)
:Gagal dengan:
Selain itu, Anda dapat menambahkan
CHECK
batasan jika Anda ingin melarang(y,y)
baris:Ada cara lain untuk mengimplementasikan ini seperti yang Anda sebutkan, seperti menyimpan hanya satu arah hubungan (dalam satu baris, bukan dua) dengan memaksa id yang lebih rendah di
x_id1
dan id yang lebih tinggi dix_id2
kolom. Tampaknya lebih mudah diterapkan, tetapi biasanya mengarah ke pertanyaan yang lebih kompleks nanti:sumber