Это на самом деле не то, что «лучше обеспечивается на стороне клиента», а то, что нецелесообразно применять в определенных реализациях базы данных. Реально работа ДОЛЖНА принадлежать базе данных, и должен работать хотя бы один из обходных путей, приведенных ниже.
В конечном счете, вы хотите ограничить родителя ребенком. Это гарантирует, что ребенок существует. К сожалению, это вызывает проблему куриного яйца, потому что дети должны указывать на одного и того же родителя, вызывая конфликт ограничений.
Для решения проблемы без видимых побочных эффектов в остальной части вашей системы требуется одна из двух способностей - ни одна из которых не обнаружена в SQL Server.
1) Отложенная проверка ограничений - Это вызывает проверку ограничений в конце транзакции. Обычно они происходят в конце утверждения. В этом корень проблемы с куриным яйцом, так как она не позволяет вставить первый дочерний или родительский ряд из-за отсутствия другого, и это решает ее.
2) Вы можете использовать CTE для вставки первого дочернего элемента, где CTE висит от оператора, который вставляет родительский элемент (или наоборот). При этом обе строки вставляются в одну и ту же инструкцию, вызывая эффект, аналогичный отложенной проверке ограничения.
3) Без них у вас нет выбора, кроме как разрешить пустые значения в одной из ссылок, чтобы вы могли вставить эту строку без проверки зависимостей. Затем вы должны вернуться и обновить ноль со ссылкой на второй ряд. Если вы используете эту технику, вы должны быть осторожны, чтобы остальная часть системы ссылалась на родительскую таблицу через представление, которое скрывает все строки с нулем в дочернем столбце ссылок.
В любом случае удаление дочерних элементов столь же сложно, поскольку вы не можете удалить дочерний элемент, который доказывает, что хотя бы один из них существует, если вы сначала не обновите родительский элемент, чтобы указать на дочерний элемент, который не будет удален.
Когда вы собираетесь удалить последнего ребенка, вы должны либо выдать ошибку, либо удалить родителя одновременно. Ошибка произойдет автоматически, если вы не установите родительский указатель на ноль в первую очередь (или отложите проверку). Если вы отложите (или установите для дочернего указателя значение NULL), вы сможете удалить дочернего элемента, а затем родительский элемент также может быть удален.
Я буквально исследовал это в течение многих лет, и я наблюдаю за каждой версией SQL Server для облегчения этой проблемы, поскольку это так часто встречается.
ПОЖАЛУЙСТА Как только у кого-то есть практическое решение, пожалуйста, напишите!
P.S. Вам нужно либо использовать составной ключ при обращении к строке подтверждения ребенка от родителя, либо с помощью триггера, чтобы убедиться, что ребенок, предоставляющий подтверждение, действительно считает эту строку своим родителем.
P.P.S Хотя верно, что null никогда не должен быть видимым для остальной части вашей системы, если вы выполняете и вставку, и обновление в одной и той же транзакции, это зависит от поведения, которое может дать сбой. Смысл этого ограничения состоит в том, чтобы гарантировать, что сбой логики не оставит вашу базу данных в недопустимом состоянии. Защищая таблицу с помощью представления, скрывающего пустые значения, любая недопустимая строка не будет видна. Очевидно, что ваша логика вставки должна учитывать возможность того, что такая строка может существовать, но она все равно нуждается в знаниях и ничего больше не нужно знать.