TL; DR
Необходимо пересмотреть целесообразность применения этого вида логики бизнес-правил в базе данных - эта проверка, вероятно, является лучшим кандидатом для вашего приложения или сохраненнойпроцедура, которая действует как хранитель вставки вместо прямой вставки новой строки в таблицу.
Игнорирование предупреждений
Тем не менее, я считаю, что то, что вы хотите, этооднако возможно в UDF-ограничении, хотя и с потенциально ужасными последствиями производительности * 1 , и, вероятно, склонен к условиям гонки в обновлениях на основе набора
Вот определенная пользователем функция, котораяприменяет уникальную логику электронной почты для обоих столбцов.Обратите внимание, что к тому времени, когда ограничение проверено, строка уже В таблице уже , поэтому сама новая строка должна быть исключена из дублирующих проверок.
Мой код также зависитдля поведения ANSI NULL, т. е. что предикаты NULL = NULL
и X IN (NULL)
оба возвращают NULL и, следовательно, исключаются из проверки на сбой (чтобы удовлетворить ваше требование, чтобы NULLS не нарушали правило).
Нам также нужно проверить, чтобы вставка ОБА новых столбцов отличалась от NULL, но дублировалась.
Итак, UDF выполняет проверку:
CREATE FUNCTION dbo.CheckUniqueEmails(@id int, @memEmail varchar(50),
@memEmailPartner varchar(50))
RETURNS bit
AS
BEGIN
DECLARE @retval bit;
IF @memEmail = @memEmailPartner
OR EXISTS (SELECT 1 FROM MyTable WHERE memEmail IS NOT NULL
AND memEmail IN(@memEmail, @memEmailPartner) AND idMember <> @id)
OR EXISTS (SELECT 1 FROM MyTable WHERE memEmailPartner IS NOT NULL
AND memEmailPartner IN(@memEmail, @memEmailPartner) AND idMember <> @id)
SET @retval = 0
ELSE
SET @retval = 1;
RETURN @retval;
END;
GO
, которая затем применяется вCHECK
ограничение:
ALTER TABLE MyTable ADD CHECK (dbo.CheckUniqueEmails(
idMember, memEmail, memEmailPartner) = 1);
Я поставил SQLFiddle здесь
Раскомментируйте «неудачные» тестовые случаи, чтобы убедиться, что вышеуказанное проверочное ограничение работает.
Я не проверял это с обновлениями, и, согласно совету Мартина по ссылке, это, вероятно, сломается при вставке с несколькими строками.
* 1 - нам нужны индексы на оба адреса электронной почтыстолбцы.