添加约束,以防止SQL更新触发副本
-
23-08-2019 - |
题
我们有一个用户表,每个用户都有一个唯一的电子邮件和用户名。我们尝试我们的代码中做到这一点,但我们要确保用户永远不会与电子邮件的用户名相同的数据库插入(或更新)。
我已经添加了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约束/索引的解决方案,只有一个空值将在该列允许的。因此,举例来说,如果你想要的电子邮件地址是可选的,它不会工作的,因为只有一个用户可以有一个空的电子邮件地址。在这种情况下,你将不得不求助于等的触发或筛选索引的另一种方法。