添加约束以防止 SQL 更新触发器中出现重复

发布于 2024-07-14 03:45:24 字数 2066 浏览 6 评论 0原文

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

We have a user table, every user has an unique email and username. We try to do this within our code but we want to be sure users are never inserted (or updated) in the database with the same username of email.
I've added a BEFORE INSERT Trigger which prevents the insertion of duplicate users.

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

But for the Update trigger I have no Idea how to do this.
I've found this example with google:
http://www.devarticles.com/c/a/SQL-Server/Using-Triggers-In-MS-SQL-Server/2/
But I don't know if it applies when you update multiple columns at once.

EDIT:

I've tried to add a unique constraint on these columns but it doesn't work:

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

别理我 2024-07-21 03:45:24

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

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

You can add a unique contraint on the table, this will raise an error if you try and insert or update and create duplicates

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

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

EDIT: Ok, i've just read your comments to another post and seen that you're using NVARCHAR(MAX) as your data type. Is there a reason why you might want more than 4000 characters for an email address or username? This is where your problem lies. If you reduce this to NVARCHAR(250) or thereabouts then you can use a unique index.

踏雪无痕 2024-07-21 03:45:24

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

Sounds like a lot of work instead of just using one or more unique indexes. Is there a reason you haven't gone the index route?

甜是你 2024-07-21 03:45:24

为什么不在数据库中的列上使用 UNIQUE 属性呢? 设置该设置将使 SQL Server 强制执行该操作,并在您尝试插入重复项时抛出错误。

Why not just use the UNIQUE attribute on the column in your database? Setting that will make the SQL server enforce that and throw an error if you try to insert a dupe.

梦醒灬来后我 2024-07-21 03:45:24

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

You should use a SQL UNIQUE constraint on each of these columns for that.

蓝礼 2024-07-21 03:45:24

只要 NVARCHAR(450) 或更小,您就可以在 NVARCHAR 上创建 UNIQUE INDEX

您真的需要这么大的 UNIQUE 列吗?

You can create a UNIQUE INDEX on an NVARCHAR as soon as it's an NVARCHAR(450) or less.

Do you really need a UNIQUE column to be so large?

千年*琉璃梦 2024-07-21 03:45:24

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

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

In general, I would avoid Triggers wherever possible as they can make the behaviour very hard to understand unless you know that the trigger exists. As other commentatators have said, a unique constraint is the way to go (once you have amended your column definitions to allow it).

If you ever find yourself needing to use a trigger, it may be a sign that your design is flawed. Think hard about why you need it and whether it is performing logic that belongs elsewhere.

猥琐帝 2024-07-21 03:45:24

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

Be aware that if you use the UNIQUE constraint/index solution with SQL Server, only one null value will be permitted in that column. So, for example, if you wanted the email address to be optional, it wouldn't work, because only one user could have a null email address. In that case, you would have to resort to another approach like a trigger or a filtered index.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文