1

我们有一个用户表,每个用户都有一个唯一的电子邮件和用户名。我们尝试在我们的代码中执行此操作,但我们希望确保用户永远不会使用相同的电子邮件用户名插入(或更新)到数据库中。我添加了一个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-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.
4

7 回答 7

13

您可以在表上添加唯一约束,如果您尝试插入或更新并创建重复项,这将引发错误

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) 或附近,那么您可以使用唯一索引。

于 2009-02-13T14:31:21.763 回答
5

听起来需要做很多工作,而不是仅仅使用一个或多个唯一索引。你没有走索引路线是有原因的吗?

于 2009-02-13T14:25:50.997 回答
2

为什么不在数据库中的列上使用 UNIQUE 属性?如果您尝试插入欺骗,设置将使 SQL 服务器强制执行并引发错误。

于 2009-02-13T14:27:21.973 回答
2

为此,您应该对这些列中的每一列使用 SQLUNIQUE约束。

于 2009-02-13T14:28:17.400 回答
1

只要它是一个或更少,您就可以在一个UNIQUE INDEX上创建一个。NVARCHARNVARCHAR(450)

你真的需要UNIQUE这么大的柱子吗?

于 2009-02-13T14:39:37.280 回答
0

一般来说,我会尽可能避免使用触发器,因为除非您知道触发器存在,否则它们会使行为非常难以理解。正如其他评论员所说,唯一的约束是要走的路(一旦您修改了列定义以允许它)。

如果您发现自己需要使用触发器,这可能表明您的设计存在缺陷。仔细想想你为什么需要它,以及它是否正在执行属于其他地方的逻辑。

于 2009-02-13T14:53:15.767 回答
0

请注意,如果您在 SQL Server 中使用 UNIQUE 约束/索引解决方案,则该列中只允许一个空值。因此,例如,如果您希望电子邮件地址是可选的,它就行不通,因为只有一个用户可以有一个空电子邮件地址。在这种情况下,您将不得不求助于另一种方法,例如触发器或过滤索引。

于 2009-07-04T01:11:01.520 回答