I have the following two tables, that will define distribution rates from items on table A to other items on table A (I think I can say B defines a many-to-many relationship for A with itself).
create table A (
code char(5) not null primary key,
desc varchar(50) not null
)
create table B (
code1 char(5) not null,
code2 char(5) not null,
perc numeric(6,2) not null,
constraint pk_B primary key (code1, code2),
constraint fk_B_1 foreign key (code1) references A (code) on update cascade on delete cascade,
constraint fk_B_2 foreign key (code2) references A (code) on update cascade on delete cascade
)
I'd like to have a simple way to check if a new record being inserted on B will cause a circular reference to be created.
This example illustrates the problem:
insert into B (code1, code2, perc) values ('01.10', '02.10', 100);
insert into B (code1, code2, perc) values ('02.10', '02.11', 50);
insert into B (code1, code2, perc) values ('02.10', '02.12', 50);
insert into B (code1, code2, perc) values ('02.11', '04.10', 50);
insert into B (code1, code2, perc) values ('02.11', '02.12', 50);
insert into B (code1, code2, perc) values ('04.10', '01.10', 50);
insert into B (code1, code2, perc) values ('04.10', '04.11', 50);
This set of data would generate the following circular reference:
I'm using Firebird 2.5, but I'd prefer to use only standard sql, because portability is something I'm concerned. We might be changing DBMS soon.
Best Answer
Following @ypercube comment to the question, I came up with this solution:
If any records are returned, then new.code2 references new.code1 and there would be circular reference if this new record was inserted.
For Firebird specifically, this is what I used: