Domanda

Abbiamo una tabella utenti, ogni utente ha un'e-mail e un nome utente univoci.Cerchiamo di farlo all'interno del nostro codice ma vogliamo essere sicuri che gli utenti non vengano mai inseriti (o aggiornati) nel database con lo stesso nome utente dell'email.Ho aggiunto un BEFORE INSERT Trigger che impedisce l'inserimento di utenti duplicati.

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

Ma per il trigger di aggiornamento non ho idea di come farlo.Ho trovato questo esempio con Google:http://www.devarticles.com/c/a/SQL-Server/Using-Triggers-In-MS-SQL-Server/2/Ma non so se si applica quando aggiorni più colonne contemporaneamente.

MODIFICARE:

Ho provato ad aggiungere un vincolo univoco su queste colonne ma non funziona:

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.
È stato utile?

Soluzione

È possibile aggiungere un contraint univoco nella tabella, tale da far salire un errore se si tenta di inserire o aggiornare e creare duplicati

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

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

EDIT: Ok, ho appena letto i vostri commenti ad un altro posto e visto che si sta utilizzando NVARCHAR (MAX) come tipo di dati. C'è un motivo per cui si potrebbe desiderare di più di 4000 caratteri per un indirizzo email o nome utente? Questo è dove il vostro problema. Se si riduce questo per NVARCHAR (250) o giù di lì, allora è possibile utilizzare un indice univoco.

Altri suggerimenti

Sembra molto lavoro invece di utilizzare solo uno o più indici univoci.C'è un motivo per cui non hai seguito il percorso dell'indice?

Perché non usare l'attributo univoco per la colonna nel database? Impostazione che renderà il server SQL far rispettare questo e genera un errore se si tenta di inserire una vittima.

Si dovrebbe usare un vincolo di SQL UNIQUE su ciascuna di queste colonne per questo.

È possibile creare un UNIQUE INDEX su un NVARCHAR non appena si tratta di un NVARCHAR(450) o meno.

Avete veramente bisogno di una colonna UNIQUE per essere così grande?

In generale, vorrei evitare trigger per quanto possibile in quanto possono rendere il comportamento molto difficile da capire se non sai che esiste il grilletto. Come altri commentatators hanno detto, un vincolo univoco è la strada da percorrere (una volta che avete modificato i vostri definizioni di colonna per permettergli).

Se mai trovate a dover utilizzare un trigger, può essere un segno che il vostro disegno è viziata. Riflettere sul perché avete bisogno e se si sta eseguendo logica che appartiene altrove.

Si noti che se si utilizza la soluzione di vincolo / indice UNIQUE con SQL Server, un solo valore nullo sarà permesso in quella colonna. Così, per esempio, se si voleva l'indirizzo e-mail per essere opzionale, non funzionerebbe, perché solo un utente potrebbe avere un indirizzo di posta elettronica nullo. In tal caso, si dovrà ricorrere ad un altro approccio, come un trigger o un indice filtrato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top