Saya menemukan masalah desain database yang keluar dari liga saya, dan guru saya yang masuk DBA tidak aktif.
Intinya, saya punya meja dengan kunci utama berikut (PK untuk singkatnya):
child_id integer
parent_id integer
date datetime
child_id
dan parent_id
kunci asing ke tabel entitas. Tabel "child" itu sendiri juga berisi kunci asing ke tabel "parent", dan lihat, masing-masing child_id
selalu referensi sama parent_id
seperti yang diharapkan oleh tabel di atas. Bahkan, ternyata ada beberapa kode tambahan yang menjaga keduanya tetap sinkron.
Yang membuat pemula normalisasi yang terlalu bersemangat ini mengatakan, "Saya harus menghapus redundansi sebagai gantinya!"
Saya menguraikan sebagai berikut:
Table_1 PK:
child_id integer
date datetime
Table_2 PK:
parent_id integer
date datetime
Table_3: (already exists)
child_id integer PRIMARY KEY
parent_id integer FOREIGN KEY
Dan lihatlah, ketika saya bergabung dengan orang-orang ini secara alami, saya memulihkan tabel aslinya. Pemahaman saya yang membuat 5NF ini.
Namun, sekarang saya menyadari ada aturan bisnis yang tersembunyi.
Biasanya, tanggal yang terkait dengan yang diberikan child_id
harus merupakan bagian dari tanggal yang terkait dengan yang bersangkutan parent_id
. Anda dapat melihat bahwa tabel pertama menegakkan aturan ini.
Dekomposisi saya tidak memberlakukan aturan, karena Anda dapat dengan bebas menambahkan ke Tabel 1 sampai tanggal terlalu besar.
Yang menuntun saya ke sini, dengan pertanyaan-pertanyaan berikut:
Apakah 5NF dekomposisi ini? Meskipun saya akan mengatakan itu memungkinkan anomali penyisipan, tampaknya juga mengikuti contoh Wiki, yang dengan sendirinya mengikuti panduan ini . Ungkapan (penekanan saya) "kita dapat merekonstruksi semua fakta sebenarnya dari bentuk yang dinormalisasi yang terdiri dari tiga jenis catatan yang terpisah" memberi saya jeda khusus, karena tidak peduli berapa banyak sampah yang saya pompakan
Table_1
, gabungan alami masih mengabaikannya.Andaikata saya tidak suka dekomposisi ini (saya tidak). Saya dengan bebas mengakui bahwa solusi praktisnya adalah meninggalkan tabel dan kode sebagaimana adanya. Tetapi, secara teori, apakah ada cara untuk menguraikan dan / atau menambah kendala sehingga saya bisa keluar dari tabel pertama dan mempertahankan aturan bisnis saya?
Jawaban:
Normalisasi didasarkan pada dependensi fungsional. Ketergantungan fungsional berkaitan dengan semantik; mereka harus melakukan apa artinya data . Ketika Anda menyederhanakan masalah dunia nyata ke tingkat "parent_id, child_id, date", dan Anda tidak menyertakan data sampel apa pun, Anda benar-benar membatasi berapa banyak bantuan yang dapat diberikan oleh perancang basis data yang teliti kepada Anda.
Fakta bahwa Anda memiliki kunci {child_id, parent_id, date} dalam satu tabel, dan bahwa Anda memiliki (tampaknya) pasangan unik {child_id, parent_id} di tabel anak tidak selalu berarti bahwa bagian dari kombinasi itu berlebihan . Ini mungkin berarti bahwa dalam tabel yang memiliki {child_id, parent_id, date} sebagai kunci utama, pasangan atribut {child_id, parent_id} harus merujuk tabel anak di tempat pertama.
Jika itu masalahnya, Anda dapat menggunakan
FOREIGN KEY (child_id, parent_id) REFERENCES child (child_id, parent_id)
. Untuk melakukan itu, Anda memerlukan batasan UNIQUE pada pasangan kolom (child_id, parent_id) di tabel "child", yang seharusnya tidak menjadi masalah jika child_id adalah kunci utamanya.Tetapi tidak ada cara untuk mengetahui tanpa mengetahui apa artinya data, dan Anda adalah satu-satunya di utas ini yang tahu itu. (Tapi kami akan dengan senang hati membiarkan Anda menjelaskannya kepada kami.)
Sejauh menyangkut tabel asli, Anda tampaknya mengatakan bahwa child_id -> parent_id. Jika itu masalahnya, mengapa parent_id ada di dalam tabel asli? Mengapa kuncinya tidak adil (child_id, date), dengan referensi kunci asing ke tabel "child"? Bagi saya sepertinya jenis redundansi yang sedang Anda bicarakan mungkin dapat diatasi dengan menjatuhkan kolom "parent_id".
SQL DDL dan sampel data dalam bentuk pernyataan INSERT membantu kami membantu Anda. Pernyataan DDL dan INSERT lebih tepat daripada deskripsi.
sumber
Coba ini...
(child_id,parent_id)
dalam tabel anak(PK,FK:child_id, PK,FK:parent_id, PK:date)
tetap seperti itu, FK berada di 2 kolom dengan batasan unik baruatau
(PK,FK:child_id, FK:parent_id)
yaitu 1: 1 dengan anak(PK,FK: child_id, PK,FK: parent_id, PK:date)
tetap apa adanya. tetapi FK ada di 2 kolom ke tabel baruJika tidak ada yang lain, itu mungkin menginspirasi Anda ...
Jika saya mengerti dengan benar, itu akan menghapus redundansi dan kode ...
sumber