Pergunta

Nós temos uma tabela de usuário, cada usuário tem um e-mail exclusivo e nome de usuário. Tentamos fazer isso dentro de nosso código, mas queremos ter certeza de usuários nunca são inseridos (ou atualizado) no banco de dados com o mesmo nome de usuário de e-mail. Eu adicionei um BEFORE INSERT gatilho que impede a inserção de usuários duplicados.

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

Mas para o gatilho de atualização Eu não tenho nenhuma idéia de como fazer isso. Eu encontrei este exemplo com o Google: http: // www .devarticles.com / c / a / SQL-Server / Usando-disparadores-in-MS-SQL-Server / 2 / Mas eu não sei se ele se aplica quando você atualizar várias colunas ao mesmo tempo.

EDIT:

Eu tentei adicionar uma restrição exclusiva sobre essas colunas, mas ele não funciona:

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.
Foi útil?

Solução

Você pode adicionar um contraint exclusivo na tabela, isso vai gerar um erro se você tentar inserir ou atualizar e criar duplicatas

ALTER TABLE [Users] ADD  CONSTRAINT [IX_UniqueUserEmail] UNIQUE NONCLUSTERED 
(
    [Email] ASC
)

ALTER TABLE [Users] ADD  CONSTRAINT [IX_UniqueUserName] UNIQUE NONCLUSTERED 
(
    [UserName] ASC
)

EDIT: Ok, eu acabei de ler seus comentários para um outro post e visto que você está usando NVARCHAR (MAX) como seu tipo de dados. Existe uma razão pela qual você pode querer mais de 4000 caracteres para um endereço de e-mail ou nome de usuário? Este é o lugar onde o problema reside. Se você reduzir isso para NVARCHAR (250) ou por aí, então você pode usar um índice exclusivo.

Outras dicas

soa como um monte de trabalho em vez de apenas usando um ou mais originais índices. Existe uma razão para você não ter ido a rota índice?

Por que não usar o atributo exclusivo na coluna em seu banco de dados? Definir que fará com que o servidor SQL impor isso e lançar um erro se você tentar inserir um joguete.

Você deve usar uma restrição SQL UNIQUE em cada uma dessas colunas para isso.

Você pode criar um UNIQUE INDEX em um NVARCHAR assim que é uma NVARCHAR(450) ou menos.

Você realmente precisa de uma coluna UNIQUE ser tão grande?

Em geral, gostaria de evitar os gatilhos sempre que possível, como eles podem fazer o comportamento muito difícil de entender se você não sabe que existe o gatilho. Como outros commentatators ter dito, uma restrição exclusiva é o caminho a percorrer (depois de ter alterado as suas definições de coluna para permitir que ele).

Se você alguma vez encontrar-se a necessidade de usar um gatilho, pode ser um sinal de que seu projeto é falho. Pense bem sobre porque você precisa dele e se ele está executando lógica que pertence em outro lugar.

Esteja ciente de que se você usar a solução de restrição / UNIQUE com o SQL Server, apenas um valor nulo será permitida nessa coluna. Assim, por exemplo, se você queria o endereço de email a ser opcional, ele não iria funcionar, porque apenas um usuário pode ter um endereço nulo e-mail. Nesse caso, você teria que recorrer a uma outra abordagem como um gatilho ou um índice filtrado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top