Saya menemukan situasi dalam database cukup sering di mana tabel yang diberikan dapat FK ke salah satu dari sejumlah tabel induk. Saya telah melihat dua solusi untuk masalah ini, tetapi tidak ada yang secara pribadi memuaskan. Saya ingin tahu pola apa yang telah Anda lihat di sana? Apakah ada cara yang lebih baik untuk melakukannya?
Sebuah Contoh Yang Diciptakan
Misalkan sistem saya memiliki Alerts
. Lansiran dapat diterima untuk berbagai objek - Pelanggan, Berita, dan Produk. Lansiran yang diberikan bisa untuk satu-dan-hanya satu item. Untuk alasan apa pun Pelanggan, Artikel, dan Produk bergerak cepat (atau dilokalkan) sehingga teks / data yang diperlukan tidak dapat ditarik ke dalam Lansiran saat membuat Lansiran. Dengan pengaturan ini, saya telah melihat dua solusi.
Catatan: DDL di bawah ini untuk SQL Server tetapi pertanyaan saya harus berlaku untuk DBMS.
Solusi 1 - Beberapa FKeys Dapat Diabaikan
Dalam solusi ini tabel yang menautkan ke satu dari banyak tabel memiliki beberapa Kolom FK (untuk singkatnya, DDL di bawah ini tidak menunjukkan pembuatan FK). BAIK - Dalam solusi ini, menyenangkan bahwa saya memiliki kunci asing. Null-optinality dari FK membuat ini nyaman dan relatif mudah untuk menambahkan data yang akurat. THE BAD Querying tidak bagus karena membutuhkan pernyataan N LEFT JOINS atau N UNION untuk mendapatkan data terkait. Dalam SQL Server, secara khusus LEFT JOIN mencegah pembuatan tampilan yang diindeks.
CREATE TABLE Product (
ProductID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
CustomerID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
NewsID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_News Primary Key CLUSTERED (NewsID)
)
CREATE TABLE Alert (
AlertID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
ProductID int null,
NewsID int null,
CustomerID int null,
CONSTRAINT PK_Alert Primary Key CLUSTERED (AlertID)
)
ALTER TABLE Alert WITH CHECK ADD CONSTRAINT CK_OnlyOneFKAllowed
CHECK (
(ProductID is not null AND NewsID is null and CustomerID is null) OR
(ProductID is null AND NewsID is not null and CustomerID is null) OR
(ProductID is null AND NewsID is null and CustomerID is not null)
)
Solusi 2 - Satu FK di setiap Tabel Induk
Dalam solusi ini setiap tabel 'induk' memiliki FK ke tabel Alert. Itu membuatnya mudah untuk mengambil peringatan yang terkait dengan orang tua. Di sisi bawah, tidak ada rantai nyata dari Siaga ke siapa referensi. Lebih lanjut, model data memungkinkan untuk Peringatan yatim - di mana peringatan tidak terkait dengan Produk, Berita, atau Pelanggan. Sekali lagi, beberapa KIRI BERGABUNG untuk mencari tahu asosiasi.
CREATE TABLE Product (
ProductID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
CustomerID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
NewsID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_News Primary Key CLUSTERED (NewsID)
)
CREATE TABLE Alert (
AlertID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
CONSTRAINT PK_Alert Primary Key CLUSTERED (AlertID)
)
Apakah ini hanya kehidupan dalam database relasi? Apakah ada solusi alternatif yang menurut Anda lebih memuaskan?
sumber
Alertable
. Itu masuk akal?Jawaban:
Saya memahami solusi kedua yang tidak berlaku karena tidak menawarkan satu (objek) -untuk-banyak (peringatan) hubungan.
Anda terjebak hanya pada dua solusi karena kepatuhan 3NF yang ketat.
Saya akan merancang skema kopling yang lebih rendah:
Atau, jika hubungan integritas wajib, saya dapat merancang:
Bagaimanapun...
Tiga solusi yang valid plus yang lain untuk dipertimbangkan untuk banyak (objek) -untuk satu (peringatan) hubungan ...
Ini disajikan, apa moralnya?
Mereka berbeda secara halus, dan bobot yang sama pada kriteria:
Jadi, pilih comfier itu untuk Anda.
sumber
Saya telah menggunakan tabel bergabung yang dipicu-dipicu. solusi berfungsi dengan baik sebagai pilihan terakhir jika refactoring db tidak mungkin atau diinginkan. Idenya adalah bahwa Anda memiliki tabel yang hanya ada untuk menangani masalah RI, dan semua DRI menentangnya.
sumber