Добавление ограничения для предотвращения дубликатов в триггере обновлений SQL - PullRequest
0 голосов
/ 13 февраля 2009

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

EDIT:

Я пытался добавить уникальное ограничение для этих столбцов, но оно не работает:

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.

Ответы [ 7 ]

12 голосов
/ 13 февраля 2009

Вы можете добавить уникальный запрет на таблицу, это вызовет ошибку, если вы попытаетесь вставить или обновить и создать дубликаты

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) или около того, вы можете использовать уникальный индекс.

4 голосов
/ 13 февраля 2009

Звучит как большая работа, вместо использования одного или нескольких уникальных индексов. Есть ли причина, по которой вы не пошли по маршруту индекса?

1 голос
/ 13 февраля 2009

Для этого вы должны использовать ограничение SQL UNIQUE для каждого из этих столбцов.

1 голос
/ 13 февраля 2009

Почему бы просто не использовать атрибут UNIQUE для столбца в вашей базе данных? Параметр, который заставит SQL-сервер применять это и выдает ошибку, если вы попытаетесь вставить обман.

0 голосов
/ 04 июля 2009

Имейте в виду, что если вы используете решение для ограничения / индекса UNIQUE с SQL Server, в этом столбце будет разрешено только одно нулевое значение. Так, например, если вы хотите, чтобы адрес электронной почты был необязательным, он не работал бы, потому что только один пользователь мог иметь нулевой адрес электронной почты. В этом случае вам придется прибегнуть к другому подходу, например к триггеру или отфильтрованному индексу.

0 голосов
/ 13 февраля 2009

В общем, я бы по возможности избегал триггеров, поскольку они могут очень затруднить понимание поведения, если вы не знаете, что триггер существует. Как говорили другие комментаторы, единственный способ - это ограничение (после того, как вы изменили определения столбцов, чтобы разрешить его).

Если вам когда-нибудь понадобится использовать триггер, это может быть признаком того, что ваш дизайн имеет недостатки. Подумайте о том, зачем вам это нужно, и выполняет ли оно логику, которая принадлежит другому.

0 голосов
/ 13 февраля 2009

Вы можете создать UNIQUE INDEX для NVARCHAR, как только это будет NVARCHAR(450) или меньше.

Вам действительно нужен столбец UNIQUE, чтобы быть таким большим?

...