Tidak ada aturan umum atau Praktik Terbaik, kunci asing tidak boleh dibatalkan. Sering kali masuk akal bagi suatu entitas untuk tidak memiliki hubungan dengan entitas lain. Misalnya, Anda mungkin memiliki daftar artis yang Anda lacak tetapi, saat ini, Anda tidak memiliki CD yang direkam oleh artis tersebut.
Adapun untuk memiliki Media (CD, DVD, BluRay) yang dapat berupa musik/audio atau perangkat lunak, Anda dapat memiliki tabel dengan informasi yang sama dan kemudian dua kunci asing, satu untuk setiap tabel ekstensi (AudioData dan SoftwareData), tetapi satu harus NULL
. Ini menghadirkan situasi yang disebut, antara lain, busur eksklusif. Ini umumnya dianggap...bermasalah.
Pikirkan superclass dan dua kelas turunan dalam bahasa OO seperti Java atau C++. Salah satu cara untuk merepresentasikannya dalam skema relasional adalah:
create table Media(
ID int not null, -- identity, auto_generated, generated always as identity...
Type char( 1 ) not null,
Format char( 1 ) not null,
... <other common data>,
constraint PK_Media primary key( ID ),
constraint FK_Media_Type foreign key( Type )
references MediaTypes( ID ), -- A-A/V, S-Software, G-Game
constraint FK_Media_Format foreign key( Format )
references MediaFormats( ID ) -- C-CD, D-DVD, B-BluRay, etc.
);
create unique index UQ_Media_ID_Type( ID, Type ) on Media;
create table AVData( -- For music and video
ID int not null,
Type char( 1 ) not null,
... <audio-only data>,
constraint PK_AVData primary key( ID ),
constraint CK_AVData_Type check( Type = 'A',
constraint FK_AVData_Media foreign key( ID, Type )
references Media( ID, Type )
);
create table SWData( -- For software, data
ID int not null,
Type char( 1 ) not null,
... <software-only data>,
constraint PK_SWData primary key( ID ),
constraint CK_SWData_Type check( Type = 'S',
constraint FK_SWData_Media foreign key( ID, Type )
references Media( ID, Type )
);
create table GameData( -- For games
ID int not null,
Type char( 1 ) not null,
... <game-only data>,
constraint PK_GameData primary key( ID ),
constraint CK_GameData_Type check( Type = 'G',
constraint FK_GameData_Media foreign key( ID, Type )
references Media( ID, Type )
);
Sekarang jika Anda mencari film, Anda mencari tabel AVData, lalu bergabung dengan tabel Media untuk informasi lainnya dan seterusnya dengan perangkat lunak atau game. Jika Anda memiliki nilai ID tetapi tidak tahu jenisnya, cari tabel Media dan nilai Type akan memberi tahu Anda yang mana dari tiga (atau lebih) tabel data yang akan digabungkan. Intinya adalah bahwa FK merujuk ke tabel generik, bukan darinya.
Tentu saja, sebuah film atau game atau perangkat lunak dapat dirilis pada lebih dari satu jenis media, sehingga Anda dapat memiliki tabel persimpangan antara Media
tabel dan tabel data masing-masing. Otoh, itu umumnya diberi label dengan SKU yang berbeda sehingga Anda mungkin juga ingin memperlakukannya sebagai item yang berbeda.
Kodenya, seperti yang Anda duga, bisa menjadi cukup rumit, meskipun tidak terlalu buruk. Otoh, tujuan desain kami bukanlah kesederhanaan kode tetapi integritas data. Hal ini membuat tidak mungkin untuk mencampur, misalnya, data game dengan item film. Dan Anda menghilangkan sekumpulan bidang di mana hanya satu yang harus memiliki nilai dan yang lainnya harus nol.