Desain database: Dua hubungan 1 ke banyak ke tabel yang sama


20

Saya harus memodelkan situasi di mana saya memiliki tabel Chequing_Account (yang berisi anggaran, nomor iban, dan detail akun lainnya) yang harus dikaitkan dengan dua tabel yang berbeda, Person dan Corporation yang keduanya dapat memiliki 0, 1 atau banyak akun chequing.

Dengan kata lain saya memiliki dua hubungan 1-ke-banyak dengan akun Chequing tabel yang sama

Saya ingin mendengar solusi untuk masalah ini yang menghormati persyaratan normalisasi. Sebagian besar solusi yang saya dengar adalah:

1) menemukan entitas yang sama yang dimiliki oleh Person dan Corporation dan membuat tabel tautan antara ini dan tabel Chequing_Account, ini tidak mungkin dalam kasus saya dan bahkan jika saya ingin menyelesaikan masalah umum dan bukan contoh khusus ini.

2) Buat dua tabel tautan PersonToChequingAccount dan CorporationToChequingAccount yang menghubungkan kedua entitas dengan Akun Chequing. Namun saya tidak ingin dua Orang memiliki akun pemalsuan yang sama, dan saya tidak ingin orang biasa dan Perusahaan berbagi akun pemalsuan! lihat gambar ini

http://i41.tinypic.com/35i6kbk.png

3) Buat dua kunci asing di Akun Chequing yang mengarah ke Korporasi dan Orang Alami, namun saya akan menegaskan bahwa Seseorang dan Perusahaan dapat memiliki banyak akun chequing, namun saya harus memastikan secara manual bahwa untuk setiap baris ChequingAccount tidak semua hubungan menunjuk ke Korporasi dan orang Alami karena akun checquing adalah dari korporasi atau Orang Alami. lihat gambar ini

http://i40.tinypic.com/1rpv9z.png

Apakah ada solusi pembersih lain untuk masalah ini?


Pernahkah Anda berpikir untuk memiliki misalnya OwnerTypeIDdi ChecquingAccountmeja, dengan 1=Corporationdan 2=NaturalPerson? Dengan begitu Anda hanya perlu satu OwnerIDdi ChecquingAccounttabel, yang dapat Anda indeks bersama dengan OwnerTypeID.
RoKa

Saya tidak hanya perlu tahu apakah itu perusahaan atau orang alami tetapi juga untuk mengetahui id masing-masing, jadi saya perlu nomor id dan tidak hanya nilai 1 atau 2! Solusi 3 adalah apa yang saya temukan di sini saya memiliki dua kolom dengan id untuk korporasi atau orang perorangan
dendini

2
Ya, solusi adalah opsi yang valid. Dalam sebagian besar DBMS Anda dapat menegakkan bahwa hanya satu dari dua FK yang "aktif" dengan batasan pemeriksaan: CHECK (CorporationID IS NOT NULL AND NaturalPersonID IS NULL OR CorporationID IS NULL AND NaturalPersonID IS NOT NULL)Saya lebih suka solusi 1 (tapi itu hanya saya). Jauh lebih "bersih".
ypercubeᵀᴹ

Ya, saya mengerti, tetapi Anda dapat memiliki ChecquingAccountcatatan di dalam tabel OwnerTypeID=1dan OwnerID=123, menunjukkan bahwa itu adalah tipe Corporation, oleh karena itu ID 123di dalam Corporationtabel. OwnerTypeID memberi tahu Anda tabel mana, dan OwnerID memberi tahu Anda ID di tabel itu.
RoKa

1
Bagaimana opsi # 1 tidak mungkin? Kata "Korporasi" pada dasarnya berarti "bisnis yang secara hukum adalah seseorang," setelah semua. Sebut saja Customersmeja.
Jon of All Trades

Jawaban:


15

Database relasional tidak dibangun untuk menangani situasi ini dengan sempurna. Anda harus memutuskan apa yang paling penting bagi Anda dan kemudian membuat trade-off Anda. Anda memiliki beberapa tujuan:

  • Pertahankan bentuk normal ketiga
  • Pertahankan integritas referensial
  • Pertahankan batasan bahwa setiap akun milik korporasi atau orang alami.
  • Pertahankan kemampuan untuk mengambil data secara sederhana dan langsung

Masalahnya adalah bahwa beberapa tujuan ini saling bersaing.

Solusi Sub-Pengetikan
Anda dapat memilih solusi sub-pengetikan tempat Anda membuat tipe-super yang menggabungkan korporasi dan orang. Super-type ini mungkin akan memiliki kunci majemuk dari kunci alami dari sub-tipe plus atribut partisi (misalnya customer_type). Ini bagus sejauh normalisasi berjalan dan memungkinkan Anda untuk menegakkan integritas referensial serta kendala bahwa perusahaan dan orang-orang saling eksklusif. Masalahnya adalah hal ini membuat pengambilan data lebih sulit, karena Anda selalu harus melakukan percabangan berdasarkan customer_typesaat Anda bergabung dengan akun ke pemegang akun. Ini mungkin berarti menggunakan UNIONdan memiliki banyak SQL berulang dalam permintaan Anda.

Solusi Dua Kunci Asing
Anda bisa memilih solusi di mana Anda menyimpan dua kunci asing di tabel akun Anda, satu untuk perusahaan dan satu untuk orang. Solusi ini juga memungkinkan Anda untuk mempertahankan integritas referensial, normalisasi, dan eksklusivitas bersama. Ini juga memiliki kelemahan pengambilan data yang sama dengan solusi sub-mengetik. Sebenarnya, solusi ini sama seperti solusi sub-pengetikan kecuali bahwa Anda mendapatkan masalah percabangan logika bergabung Anda "lebih cepat".

Namun demikian, banyak pemodel data akan menganggap solusi ini lebih rendah daripada solusi sub-pengetikan karena cara kendala saling eksklusivitas diberlakukan. Dalam solusi pengetikan Anda menggunakan kunci untuk menegakkan eksklusivitas timbal balik. Dalam dua solusi kunci asing Anda menggunakan CHECKbatasan. Saya kenal beberapa orang yang memiliki bias yang tidak dapat dibenarkan terhadap kendala pemeriksaan. Orang-orang ini akan lebih suka solusi yang menjaga kendala dalam kunci.

Solusi Atribut Pemisahan yang "Dinormalisasi"
Ada opsi lain di mana Anda menyimpan satu kolom kunci asing di tabel akun yang menarik dan menggunakan kolom lain untuk memberi tahu Anda bagaimana menafsirkan kolom kunci asing (RoKaOwnerTypeIDkolom). Ini pada dasarnya menghilangkan tabel super-type dalam solusi sub-mengetik dengan mendenormalkan atribut partisi ke tabel anak. (Perhatikan bahwa ini tidak sepenuhnya "denormalisasi" sesuai dengan definisi formal, karena atribut partisi adalah bagian dari kunci utama.) Solusi ini tampaknya cukup sederhana karena ia tidak memiliki tabel tambahan untuk melakukan lebih kurang hal yang sama dan itu memotong jumlah kolom kunci asing menjadi satu. Masalah dengan solusi ini adalah bahwa itu tidak menghindari percabangan logika pengambilan dan terlebih lagi, itu tidak memungkinkan Anda untuk mempertahankan integritas referensial deklaratif . Database SQL tidak memiliki kemampuan untuk mengelola kolom kunci asing tunggal untuk salah satu dari beberapa tabel induk.

Shared Domain Key Solution Utama
Salah satu cara orang kadang-kadang berurusan dengan masalah ini adalah dengan menggunakan kumpulan ID tunggal sehingga tidak ada kebingungan untuk ID yang diberikan apakah itu milik satu sub-jenis atau lainnya. Ini mungkin akan bekerja secara alami dalam skenario perbankan, karena Anda tidak akan mengeluarkan nomor rekening bank yang sama untuk perusahaan dan orang biasa. Ini memiliki keuntungan menghindari kebutuhan akan atribut partisi. Anda bisa melakukan ini dengan atau tanpa tabel tipe super. Menggunakan tabel tipe super memungkinkan Anda menggunakan batasan deklaratif untuk menegakkan keunikan. Kalau tidak, ini harus ditegakkan secara prosedural. Solusi ini dinormalisasi tetapi itu tidak akan memungkinkan Anda untuk mempertahankan integritas referensial deklaratif kecuali Anda menyimpan tabel tipe-super. Masih tidak melakukan apa pun untuk menghindari logika pengambilan kompleks.

Karena itu Anda dapat melihat bahwa tidak benar-benar mungkin untuk memiliki desain bersih yang mengikuti semua aturan, sementara pada saat yang sama menjaga pengambilan data Anda tetap sederhana. Anda harus memutuskan di mana trade-off Anda akan berada.


Solusi saya # 2 yang termasuk dalam empat grup Anda? "Solusi Atribut Pemisahan yang Dinormalisasi" tidak cukup jelas bagi saya ..
dendini

@dendini - Anda solusi nomor 2 tidak cocok dengan salah satu solusi yang saya uraikan. Ini karena tidak sesuai dengan persyaratan akun milik satu badan hukum. Cara Anda mendefinisikan kunci utama tabel perantara, mereka adalah persimpangan banyak ke banyak. Jika kunci utama hanya corporation_id dan person_idkemudian Anda pada dasarnya akan memiliki solusi sub-mengetik, kecuali bahwa tabel tipe super akan dibagi menjadi dua dan kunci asing akan dibalik, sehingga orang tidak dapat memiliki banyak akun. Jenis ini mengalahkan tujuannya.
Joel Brown

Penjelasan yang bagus. @ JoelBrown, apa implikasi kinerja dari solusi "Dua kunci asing", dalam hal permintaan? Juga, mengingat bahwa alih-alih 2, mungkin ada 6 atau lebih kunci asing: apakah Anda masih merekomendasikan pendekatan ini atau lebih condong ke arah yang berbeda?
Amadeo Gallardo

1
@AmadeoGallardo Jawabannya adalah "itu tergantung". Permintaan terhadap kunci selalu cukup efisien, karena Anda biasanya dapat mengandalkan pemindaian indeks setidaknya, jika bukan pencarian, dan ini adalah operasi cepat. Masalahnya menjadi ketika Anda query di kedua kunci dalam solusi dua kunci asing . Di sini Anda meminta pengoptimal kueri untuk melakukan operasi salah satu / atau ini. Paling-paling ini akan menggandakan biaya permintaan, biasanya sedikit lebih buruk, karena Anda harus melakukan query terhadap satu kunci, lalu yang lain, kemudian menggabungkan hasilnya.
Joel Brown

@ JoelBrown Versi SQL masa depan yang dinormalisasi harus memungkinkan pendekatan ini dengan memungkinkan definisi kunci asing majemuk berdasarkan pada dua kolom RefIDdan di RefTablemana RefTableid tetap yang mengidentifikasi tabel target. Ada banyak kasus penggunaan untuk jenis kunci ini dan banyak mempertahankan 10 atau lebih tabel asosiasi / subtipe untuk menegakkan integritas. Untuk kasus-kasus itu saya buat ini keysendiri.
djmj
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.