Я ищу лучший способ добавить ограничение в таблицу, которая фактически является уникальным индексом для отношения между записью и остальными записями в этой таблице.
Представьте себе следующую таблицу, описывающую патрули различных охранников (из предыдущего сценария сторожа)
PK PatrolID Integer
FK GuardID Integer
Starts DateTime
Ends DateTime
Мы начнем с ограничения, указывающего, что время начала и окончания должно быть логическим:
Ends >= Starts
Однако я хочу добавить еще одно логическое ограничение: конкретный сторож (GuardID) не может находиться в двух местах одновременно, а это означает, что для любой записи период, указанный в Start / Ends, не должен перекрываться с периодом, определенным для любого другого патруль той же стражи.
Я могу придумать два способа попытаться приблизиться к этому:
Создать триггер INSTEAD OF INSERT. Этот триггер будет затем использовать курсоры для просмотра таблицы INSERTED, проверяя каждую запись. Если какая-либо запись конфликтует с существующей, возникает ошибка. У меня есть две проблемы с этим подходом: мне не нравится использовать курсоры в современной версии SQL Server, и я не уверен, как реализовать ту же логику для ОБНОВЛЕНИЙ. Также может быть сложность записей в INSERTED, конфликтующих друг с другом.
Второй, на первый взгляд, лучший подход заключается в создании CONSTRAINT, который вызывает пользовательскую функцию, передавая PatrolID, GuardID, Starts и Ends. Затем функция выполняет проверку запроса WHERE EXISTS для любых записей, которые перекрывают параметры GuardID / Starts / Ends, которые не являются исходной записью PatrolID. Однако я не уверен, какие потенциальные побочные эффекты может иметь этот подход.
Второй подход лучше? Кто-нибудь видит какие-либо подводные камни, например, при вставке / обновлении нескольких строк одновременно (здесь я обеспокоен тем, что строки в этой группе могут конфликтовать, то есть порядок, в который они «вставляются», имеет значение). Есть ли лучший способ сделать это (например, какой-нибудь причудливый трюк с INDEX?)