Один из способов сделать это - с помощью триггеров. Триггер может выполнять соединения, необходимые для обеспечения C.A = C.B-> B.A. Этот метод используется для проверки соответствия родительских ключей между родительскими, дочерними и внучатыми таблицами.
Например:
-- untested code
create trigger C_IU_Verify_A on C
for insert, update as
if exists
(
select 1
from inserted
inner join b on b.id = inserted.b_id
where b.a_id <> inserted.a_id
)
begin
raiserror('Parent table keys do not match.', 16, 1)
rollback
end
Другой способ сделать это - использовать составные первичные ключи. Определите первичный ключ B как (a_id, id). Установите внешний ключ от B (a_id) до A (id). Установите второй внешний ключ от C (a_id, b_id) до B (a_id, id). На данный момент у вас есть ссылочная целостность между C.a_id и B.a_id.
Например:
create table a (id int primary key clustered)
create table b(a_id int, id int, primary key (a_id, id), unique(id))
create table c(a_id int, b_id int, id int, primary key (a_id, b_id, id), unique(id))
alter table B add constraint fk_b_aid foreign key (a_id) REFERENCES A(id)
alter table C add constraint fk_c_aid_bid foreign key (a_id, b_id) REFERENCES B(a_id, id)
insert into a (id) select 1
insert into a (id) select 2
insert into b (a_id, id) select 1, 1
insert into b (a_id, id) select 1, 2
--insert into b (a_id, id) select 2, 1 -- error: duplicate b.id
insert into b (a_id, id) select 2, 3
--insert into b (a_id, id) select 3, 1 -- error: there is no A with id = 3
insert into c (a_id, b_id, id) select 1, 1, 1
insert into c (a_id, b_id, id) select 1, 1, 2
insert into c (a_id, b_id, id) select 1, 2, 3
insert into c (a_id, b_id, id) select 2, 3, 4
--insert into c (a_id, b_id, id) select 1, 3, 5 -- error: there is no B with B.a_id = 1 and B.id = 3
drop table c;
drop table b;
drop table a;