Saya mengalami beberapa masalah pemodelan skema listrik dalam SQL. Struktur yang ingin saya tangkap adalah
part ←────────── pin
↑ ↑
part_inst ←───── pin_inst
di mana "inst" adalah kependekan dari "instance".
Sebagai contoh, saya mungkin memiliki part
op-amp LM358 dengan pin
s 1OUT, 1IN-, 1IN +, GND, 2IN +, 2IN-, 2OUT, dan V CC . Saya kemudian dapat menempatkan bagian ini pada skema, membuat a part_inst
dan 8
pin_inst
s.
Mengabaikan bidang data, upaya awal saya pada suatu skema adalah
create table parts (
part_id bigserial primary key
);
create table pins (
pin_id bigserial primary key,
part_id bigint not null references parts
);
create table part_insts (
part_inst_id bigserial primary key,
part_id bigint not null references parts
);
create table pin_insts (
pin_inst_id bigserial primary key,
part_inst_id bigint not null references part_insts,
pin_id bigint not null references pins
);
Masalah utama dengan skema ini adalah bahwa a pin_inst
mungkin terkait part_inst
dengan part_id=1
tetapi pin
memiliki part_id=2
.
Saya ingin menghindari masalah ini pada level database daripada level aplikasi. Jadi, saya memodifikasi kunci utama saya untuk menegakkan itu. Saya menandai baris yang diubah dengan --
.
create table parts (
part_id bigserial primary key
);
create table pins (
pin_id bigserial, --
part_id bigint not null references parts,
primary key (pin_id, part_id) --
);
create table part_insts (
part_inst_id bigserial, --
part_id bigint not null references parts,
primary key (part_inst_id, part_id) --
);
create table pin_insts (
pin_inst_id bigserial primary key,
part_inst_id bigint not null, --
pin_id bigint not null, --
part_id bigint not null references parts, --
foreign key (part_inst_id, part_id) references part_insts, --
foreign key (pin_id, part_id) references pins --
);
Keluhan saya dengan metode ini adalah bahwa itu mencemari kunci utama: Di mana pun saya merujuk pada part_inst
, saya harus melacak baik itu
part_inst_id
dan part_id
. Apakah ada cara lain yang bisa saya lakukan untuk menegakkan batasan
pin_inst.part_inst.part_id = pin_inst.pin.part_id
tanpa terlalu bertele-tele?
sumber
pin_inst_id
yang merupakan redundansi juga. Anda dapat menggunakan(part_inst_id, part_id, pin_id)
kunci utama.Jawaban:
Solusi minimal
Salah satu solusi radikal mungkin dengan menghapus
pin_inst
sepenuhnya:Tidak ada dalam pertanyaan Anda untuk menyarankan Anda benar-benar membutuhkan tabel redundan. Untuk
pin
s terkait denganpart_inst
, lihatpin
s dari terkaitpart
.Itu akan menyederhanakan kode untuk:
Tetapi komentar Anda menjelaskan bahwa kami tidak akan lolos dari itu ...
Alternatif jika
pin_inst
diperlukanTermasuk yang
part_id
Anda lakukan adalah solusi paling sederhana dengan batasan kunci asing. Anda tidak dapat merujuk tabel "dua tabel jauhnya" dengan batasan kunci asing .Tapi setidaknya Anda bisa melakukannya tanpa "mencemari" kunci utama. Tambahkan
UNIQUE
kendala .Saya mengutamakan
part_id
kendala unik. Itu tidak relevan untuk integritas referensial, tetapi itu penting untuk kinerja. Kunci utama sudah menerapkan indeks untuk kolom pk. Lebih baik memiliki kolom lain terlebih dahulu di indeks multicolumn yang menerapkan kendala unik. Detail di bawah pertanyaan terkait ini:Pertanyaan terkait pada SO:
Alternatif dengan pemicu
Anda dapat menggunakan fungsi pemicu, yang lebih fleksibel, tetapi sedikit lebih rumit dan rawan kesalahan dan sedikit kurang ketat. Manfaatnya: Anda bisa melakukannya tanpa
part_inst.part_id
danpin.part_id
...sumber
pin_insts
dalamnya, tetapi saya menghapusnya untuk kepentingan keterbacaan ("Mengabaikan bidang data, [...]"). Misalnya, apin_inst
dapat ditandai sebagai input atau output.