我们有一个用户表,每个用户都有一个唯一的电子邮件和用户名。我们尝试我们的代码中做到这一点,但我们要确保用户永远不会与电子邮件的用户名相同的数据库插入(或更新)。 我已经添加了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

但对于更新触发我不知道如何做到这一点。 我发现与谷歌的这个例子: HTTP:// WWW .devarticles.com / C / A / SQL - 服务器/使用-触发器-在-MS-SQL服务器/ 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.
有帮助吗?

解决方案

您可以在表中添加独特的contraint,如果你尝试插入或更新,并创建副本,这将产生一个错误

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)或左右则可以使用一个唯一索引。

其他提示

听起来大量的工作,而不是仅仅使用一个或多个唯一索引。有没有你都没有索引路线的原因是什么?

为什么不直接使用该列唯一属性在你的数据库?设置将使SQL服务器强制执行,如果你尝试插入重复数据删除抛出异常。

您应该使用每个这些列的SQL UNIQUE约束为。

您可以在一个UNIQUE INDEX尽快创建一个NVARCHAR因为它是一个NVARCHAR(450)以下。

你真的需要一个UNIQUE列如此之大?

在一般情况下,我会避免触发尽可能因为它们可以使行为很难理解,除非你知道触发存在。至于其他commentatators说,唯一约束就是去(一旦你已经修改了你的列定义,以允许它)的方式。

如果你发现自己需要使用一个触发器,它可能是一个迹象,表明你的设计是有缺陷的。仔细想想,为什么你需要它,以及它是否正在执行属于别处的逻辑。

请注意,如果你使用SQL Server提供的UNIQUE约束/索引的解决方案,只有一个空值将在该列允许的。因此,举例来说,如果你想要的电子邮件地址是可选的,它不会工作的,因为只有一个用户可以有一个空的电子邮件地址。在这种情况下,你将不得不求助于等的触发或筛选索引的另一种方法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top