Terinspirasi oleh pertanyaan pemodelan Django: Pemodelan Basis Data dengan banyak hubungan banyak ke banyak di Django . Desain db adalah sesuatu seperti:
CREATE TABLE Book
( BookID INT NOT NULL
, BookTitle VARCHAR(200) NOT NULL
, PRIMARY KEY (BookID)
) ;
CREATE TABLE Tag
( TagID INT NOT NULL
, TagName VARCHAR(50) NOT NULL
, PRIMARY KEY (TagID)
) ;
CREATE TABLE BookTag
( BookID INT NOT NULL
, TagID INT NOT NULL
, PRIMARY KEY (BookID, TagID)
, FOREIGN KEY (BookID) REFERENCES Book (BookID)
, FOREIGN KEY (TagID) REFERENCES Tag (TagID)
) ;
CREATE TABLE Aspect
( AspectID INT NOT NULL
, AspectName VARCHAR(50) NOT NULL
, PRIMARY KEY (AspectID)
) ;
CREATE TABLE TagAspect
( TagID INT NOT NULL
, AspectID INT NOT NULL
, PRIMARY KEY (TagID, AspectID)
, FOREIGN KEY (TagID) REFERENCES Tag (TagID)
, FOREIGN KEY (AspectID) REFERENCES Aspect (AspectID)
) ;
dan masalahnya adalah bagaimana mendefinisikan BookAspectRating
tabel dan untuk menegakkan integritas referensial, jadi orang tidak dapat menambahkan peringkat untuk (Book, Aspect)
kombinasi yang tidak valid.
AFAIK, CHECK
kendala kompleks (atau ASSERTIONS
) yang melibatkan subqueries dan lebih dari satu tabel, yang mungkin bisa menyelesaikan ini, tidak tersedia di DBMS.
Gagasan lain adalah menggunakan (pseudocode) tampilan:
CREATE VIEW BookAspect_view
AS
SELECT DISTINCT
bt.BookId
, ta.AspectId
FROM
BookTag AS bt
JOIN
Tag AS t ON t.TagID = bt.TagID
JOIN
TagAspect AS ta ON ta.TagID = bt.TagID
WITH PRIMARY KEY (BookId, AspectId) ;
dan tabel yang memiliki Kunci Asing untuk Tampilan di atas:
CREATE TABLE BookAspectRating
( BookID INT NOT NULL
, AspectID INT NOT NULL
, PersonID INT NOT NULL
, Rating INT NOT NULL
, PRIMARY KEY (BookID, AspectID, PersonID)
, FOREIGN KEY (PersonID) REFERENCES Person (PersonID)
, FOREIGN KEY (BookID, AspectID)
REFERENCES BookAspect_view (BookID, AspectID)
) ;
Tiga pertanyaan:
Apakah ada DBMS yang memungkinkan (mungkin terwujud)
VIEW
dengan aPRIMARY KEY
?Apakah ada DBMS yang memungkinkan
FOREIGN KEY
bahwaREFERENCES
suatuVIEW
(dan tidak hanya basaTABLE
)?Bisakah masalah integritas ini diselesaikan sebaliknya - dengan fitur-fitur DBMS yang tersedia?
Klarifikasi:
Karena mungkin tidak ada solusi yang memuaskan 100% - dan pertanyaan Django bahkan bukan milikku! - Saya lebih tertarik pada strategi umum kemungkinan serangan terhadap masalah, bukan solusi terperinci. Jadi, jawaban seperti "dalam DBMS-X ini dapat dilakukan dengan pemicu pada tabel A" dapat diterima.
sumber
Jawaban:
Aturan bisnis ini dapat ditegakkan dalam model hanya menggunakan kendala. Tabel berikut ini akan menyelesaikan masalah Anda. Gunakan itu sebagai ganti tampilan Anda:
sumber
TagID
ke Tag lain yang terkait dengan kombinasi BookAspect yang sama.Saya pikir Anda akan menemukan bahwa dalam banyak kasus, aturan bisnis yang kompleks tidak dapat ditegakkan hanya melalui model. Ini adalah salah satu kasus di mana, setidaknya dalam SQL Server, saya pikir pemicu (lebih baik daripada pemicu) lebih baik melayani tujuan Anda.
sumber
Di Oracle, salah satu cara untuk menegakkan batasan semacam ini secara deklaratif adalah dengan membuat tampilan terwujud yang diatur untuk menyegarkan cepat pada komit yang kueri mengidentifikasi semua baris yang tidak valid (yaitu
BookAspectRating
baris yang tidak cocok denganBookAspect_view
). Anda kemudian dapat membuat batasan sepele pada tampilan terwujud yang akan dilanggar jika ada baris dalam tampilan terwujud. Ini memiliki manfaat meminimalkan jumlah data yang harus Anda duplikasi dalam tampilan terwujud. Namun, hal itu dapat menyebabkan masalah, karena kendala hanya ditegakkan pada saat Anda melakukan transaksi - banyak aplikasi tidak ditulis untuk mengharapkan bahwa operasi komit mungkin gagal - dan karena pelanggaran kendala bisa agak sulit untuk mengasosiasikan dengan baris tertentu atau tabel tertentu.sumber
SIRA_PRISE memungkinkan itu.
Meskipun FK tidak disebut "FK" lagi, tetapi hanya "batasan basis data", dan "tampilan" sebenarnya tidak harus didefinisikan sebagai tampilan, Anda hanya bisa memasukkan ekspresi definisi tampilan di dalam deklarasi the kendala basis data.
Batasan Anda akan terlihat seperti
dan kamu sudah selesai.
Namun dalam sebagian besar DBMS SQL, Anda harus melakukan analisis pada kendala Anda, menentukan bagaimana hal itu dapat dilanggar dan mengimplementasikan semua pemicu yang diperlukan.
sumber
Dalam PostgreSQL, saya tidak dapat membayangkan solusi tanpa melibatkan pemicu, tetapi tentu saja dapat dipecahkan dengan cara itu (baik itu mempertahankan pandangan terwujud semacam atau sebelum pemicu aktif
BookAspectRating
). Tidak ada kunci asing yang mereferensikan tampilan (ERROR: referenced relation "v_munkalap" is not a table
), apalagi kunci primer.sumber