Добавление ограничения для предотвращения дублирования в триггере обновления SQL.

StackOverflow https://stackoverflow.com/questions/546101

Вопрос

У нас есть таблица пользователей, каждый пользователь имеет уникальный адрес электронной почты и имя пользователя.Мы пытаемся сделать это в нашем коде, но хотим быть уверены, что пользователи никогда не будут добавлены (или обновлены) в базу данных с тем же именем пользователя, что и адрес электронной почты.Я добавил 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, в этом столбце будет разрешено только одно нулевое значение.Так, например, если вы хотите, чтобы адрес электронной почты был необязательным, это не сработает, поскольку только один пользователь может иметь нулевой адрес электронной почты.В этом случае вам придется прибегнуть к другому подходу, например, к триггеру или фильтрованному индексу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top