У меня была такая ситуация один раз. Мое решение было следующим.
В дополнение к TableA и TableMatched существовала таблица, определяющая строки, которые должны существовать в TableMatched для каждой строки в TableA. Давайте назовем это TableMatchedDomain.
Затем приложение получило доступ к TableMatched через представление, которое контролировало возвращаемые строки, например:
create view TableMatchedView
select a.ID,
d.Number,
m.OtherValues
from TableA a
join TableMatchedDomain d
left join TableMatched m on m.ID = a.ID and m.Number = d.Number
Таким образом, возвращаемые строки всегда были правильными. Если в TableMatched отсутствовали строки, то числа все равно возвращались, но с другими значениями, равными NULL. Если в TableMatched были дополнительные значения, то они вообще не возвращались, как если бы они не существовали. Изменяя строки в TableMatchedDomain, можно легко управлять этим поведением. Если бы значение было удалено TableMatchedDomain, то оно исчезло бы из представления. Если он будет добавлен снова в будущем, соответствующие значения OtherValues снова появятся, как и прежде.
Причина, по которой я разработал ее таким образом, заключалась в том, что я чувствовал, что установка неизменяемой конфигурации строки в TableMatched была слишком хрупкой и, что еще хуже, привела к избыточности. Поэтому я удалил ограничение для групп строк (в TableMatched) и вместо этого заставил все содержимое другой таблицы (TableMatchedDomain) определить правильную форму данных.