Добавление ограничения для предотвращения дублирования в триггере обновления SQL.
-
23-08-2019 - |
Вопрос
У нас есть таблица пользователей, каждый пользователь имеет уникальный адрес электронной почты и имя пользователя.Мы пытаемся сделать это в нашем коде, но хотим быть уверены, что пользователи никогда не будут добавлены (или обновлены) в базу данных с тем же именем пользователя, что и адрес электронной почты.Я добавил BEFORE INSERT
Триггер, предотвращающий добавление дубликатов пользователей.
CREATE TRIGGER [dbo].[BeforeUpdateUser]
ON [dbo].[Users]
INSTEAD OF INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @Email nvarchar(MAX)
DECLARE @UserName nvarchar(MAX)
DECLARE @UserId int
DECLARE @DoInsert bit
SET @DoInsert = 1
SELECT @Email = Email, @UserName = UserName FROM INSERTED
SELECT @UserId = UserId FROM Users WHERE Email = @Email
IF (@UserId IS NOT NULL)
BEGIN
SET @DoInsert = 0
END
SELECT @UserId = UserId FROM Users WHERE UserName = @UserName
IF (@UserId IS NOT NULL)
BEGIN
SET @DoInsert = 0
END
IF (@DoInsert = 1)
BEGIN
INSERT INTO Users
SELECT
FirstName,
LastName,
Email,
Password,
UserName,
LanguageId,
Data,
IsDeleted
FROM INSERTED
END
ELSE
BEGIN
DECLARE @ErrorMessage nvarchar(MAX)
SET @ErrorMessage =
'The username and emailadress of a user must be unique!'
RAISERROR 50001 @ErrorMessage
END
END
Но что касается триггера обновления, я понятия не имею, как это сделать.Я нашел этот пример в Google:http://www.devarticles.com/c/a/SQL-Server/Using-Triggers-In-MS-SQL-Server/2/Но я не знаю, применимо ли это при обновлении нескольких столбцов одновременно.
РЕДАКТИРОВАТЬ:
Я попытался добавить ограничение уникальности для этих столбцов, но это не сработало:
Msg 1919, Level 16, State 1, Line 1
Column 'Email' in table 'Users' is of a type
that is invalid for use as a key column in an index.
Решение
Вы можете добавить уникальное ограничение в таблицу, это вызовет ошибку, если вы попытаетесь вставить или обновить и создать дубликаты.
ALTER TABLE [Users] ADD CONSTRAINT [IX_UniqueUserEmail] UNIQUE NONCLUSTERED
(
[Email] ASC
)
ALTER TABLE [Users] ADD CONSTRAINT [IX_UniqueUserName] UNIQUE NONCLUSTERED
(
[UserName] ASC
)
РЕДАКТИРОВАТЬ:Хорошо, я только что прочитал ваши комментарии к другому сообщению и увидел, что вы используете NVARCHAR(MAX) в качестве типа данных.Есть ли причина, по которой вам может потребоваться более 4000 символов для адреса электронной почты или имени пользователя?Вот в чем ваша проблема.Если вы уменьшите это значение до NVARCHAR(250) или около того, вы сможете использовать уникальный индекс.
Другие советы
Звучит как большая работа вместо того, чтобы просто использовать один или несколько уникальных индексов.Есть ли причина, по которой вы не пошли по индексному маршруту?
Почему бы просто не использовать атрибут UNIQUE для столбца в вашей базе данных?Настройка, которая заставит SQL-сервер применять это и выдавать ошибку, если вы попытаетесь вставить дубликат.
Вы должны использовать SQL UNIQUE
ограничение для каждого из этих столбцов для этого.
Вы можете создать UNIQUE INDEX
на NVARCHAR
как только это NVARCHAR(450)
или менее.
Вам действительно нужен UNIQUE
столбец должен быть таким большим?
В общем, я бы по возможности избегал триггеров, поскольку они могут затруднить понимание поведения, если вы не знаете, что триггер существует.Как говорили другие комментаторы, нужно использовать уникальное ограничение (после того, как вы внесли изменения в определения столбцов, чтобы это разрешить).
Если вам когда-нибудь понадобится использовать триггер, это может быть признаком того, что ваш дизайн несовершенен.Подумайте хорошенько, зачем вам это нужно и выполняет ли оно какую-то другую логику.
Имейте в виду, что если вы используете решение ограничения/индекса UNIQUE с SQL Server, в этом столбце будет разрешено только одно нулевое значение.Так, например, если вы хотите, чтобы адрес электронной почты был необязательным, это не сработает, поскольку только один пользователь может иметь нулевой адрес электронной почты.В этом случае вам придется прибегнуть к другому подходу, например, к триггеру или фильтрованному индексу.