Jika Anda hanya membutuhkan 2 atau 3 kategori (tanaman / metazoa / bakteri) dan Anda ingin membuat model hubungan XOR, mungkin "busur" adalah solusi untuk Anda. Keuntungan: tidak perlu pemicu. Diagram contoh dapat ditemukan [di sini] [1]. Dalam situasi Anda, tabel "wadah" akan memiliki 3 kolom dengan batasan PERIKSA, yang memungkinkan tanaman atau hewan atau bakteri.
Ini mungkin tidak tepat jika akan ada kebutuhan untuk membedakan banyak kategori (misalnya genera, spesies, subspesies) di masa depan. Namun, untuk 2-3 grup / kategori ini dapat melakukan trik.
UPDATE: Terinspirasi oleh saran dan komentar kontributor, solusi berbeda yang memungkinkan banyak taksa (kelompok organisme terkait, diklasifikasikan oleh ahli biologi), dan menghindari nama tabel "spesifik" (PostgreSQL 9.5).
Kode DDL:
-- containers: may have more columns eg for temperature, humidity etc
create table containers (
ctr_name varchar(64) unique
);
-- taxonomy - have as many taxa as needed (not just plants/animals/bacteria)
create table taxa (
t_name varchar(64) unique
);
create table organisms (
o_id integer primary key
, o_name varchar(64)
, t_name varchar(64) references taxa(t_name)
, unique (o_id, t_name)
);
-- table for mapping containers to organisms and (their) taxon,
-- each container contains organisms of one and the same taxon
create table collection (
ctr_name varchar(64) references containers(ctr_name)
, o_id integer
, t_name varchar(64)
, unique (ctr_name, o_id)
);
-- exclude : taxa that are different from those already in a container
alter table collection
add exclude using gist (ctr_name with =, t_name with <>);
-- FK : is the o_id <-> t_name (organism-taxon) mapping correct?
alter table collection
add constraint taxon_fkey
foreign key (o_id, t_name) references organisms (o_id, t_name) ;
Data uji:
insert into containers values ('container_a'),('container_b'),('container_c');
insert into taxa values('t:plant'),('t:animal'),('t:bacterium');
insert into organisms values
(1, 'p1', 't:plant'),(2, 'p2', 't:plant'),(3, 'p3', 't:plant'),
(11, 'a1', 't:animal'),(22, 'a1', 't:animal'),(33, 'a1', 't:animal'),
(111, 'b1', 't:bacterium'),(222, 'b1', 't:bacterium'),(333, 'b1', 't:bacterium');
Pengujian:
-- several plants can be in one and the same container (3 inserts succeed)
insert into collection values ('container_a', 1, 't:plant');
insert into collection values ('container_a', 2, 't:plant');
insert into collection values ('container_a', 3, 't:plant');
-- 3 inserts that fail:
-- organism id in a container must be UNIQUE
insert into collection values ('container_a', 1, 't:plant');
-- bacteria not allowed in container_a, populated by plants (EXCLUSION at work)
insert into collection values ('container_a', 333, 't:bacterium');
-- organism with id 333 is NOT a plant -> insert prevented by FK
insert into collection values ('container_a', 333, 't:plant');
Terima kasih kepada @RDFozz dan @Evan Carroll dan @ypercube untuk masukan dan kesabaran mereka (membaca / mengoreksi jawaban saya).