Sql server 需要一种在MSSQL中只截获重复密钥异常的方法吗

Sql server 需要一种在MSSQL中只截获重复密钥异常的方法吗,sql-server,exception-handling,unique-constraint,duplicate-data,Sql Server,Exception Handling,Unique Constraint,Duplicate Data,假设您的MSSQL 2008数据库中有一个唯一的索引约束冲突,如下所示: Violation of PRIMARY KEY constraint 'PK_ManufacturerCode'. Cannot insert duplicate key in object 'dbo.ManufacturerCode'. The duplicate key value is (8410179) 目前,我正在通过一个胖客户机中的全局异常处理程序处理此异常(使用ADO在Delphi 6中编写,但这并不重要

假设您的MSSQL 2008数据库中有一个唯一的索引约束冲突,如下所示:

Violation of PRIMARY KEY constraint 'PK_ManufacturerCode'. Cannot insert duplicate key in object 'dbo.ManufacturerCode'. The duplicate key value is (8410179)
目前,我正在通过一个胖客户机中的全局异常处理程序处理此异常(使用ADO在Delphi 6中编写,但这并不重要,我计划将来确实使用C#.NET),并且异常消息被附加到日志框中

但我想亲自处理这个特定的重复键异常,并使用胖客户机自己的文本在客户机中显示适当的错误消息。我可以为match解析错误消息,但出于两个原因,我不会这样做:

  • 这不是一种正确的方法——最好依靠一些错误代码
  • 厚客户端旨在使用不同语言的MSSQL服务器版本,这些版本可能有不同的错误文本

使用带有自定义退出代码的返回或不断调用特殊存储过程来检查重复项,这并不能让我高兴起来。

AFAIK,区分重复项异常的唯一方法是解析错误消息

更好的解决方案是首先防止重复密钥异常。写入insert以避免插入重复的键,如果添加了行,请使用
@@rowcount
检查:

insert  YourTable
        (id, col1, col2)
select  1, 'a', 'b'
where   not exists
        (
        select  *
        from    YourTable yt2
        where   yt2.id = 1
        )

if @@rowcount = 0
    -- Duplicate key!

幸运的是,您不必解析文本。
SqlException
具有
Number
属性。Oberserve,返回的是什么号码,并与之匹配。这些数字定义明确。您甚至可以在其中一个系统目录表中查看它们(手头没有名称)


您最好只捕获一个非常特定的错误,而不是仅捕获所有
SqlException
s(例如)。

在ADO中,您可以在错误发生后访问connections属性,并检查
NativeError
属性以获取SQL Server特定的错误号

切换到.NET时,将显示与或的
number
属性相同的数字


但是,查找特定的错误号可能有点麻烦-对于重复键,它是错误号2627。

问题在于MSSQL和胖客户端之间的通信(当@rowcount=0时发生的事情)而不是关于如何检测重复密钥。我解释了您的标题
需要一种方法在MSSQL中只截获重复密钥异常,因为您只关心重复密钥异常。我认为Andomar这样做了,因此您可能需要重新表述这个问题。请注意,如果同时访问
您的表
,您需要正确管理锁定。有可能在其他人将重复值插入表之前,
@@rowcount
返回零;假定已为下一个操作锁定表的代码可能没有这样做,并将导致检查时不存在的重复行出错。我认为您的答案不错,但。。。我可以用这种方法检测发生在哪个列上的冲突吗?不,很遗憾,这需要解析消息。一般来说,我建议您只尝试插入已知的良好数据。插入前检查。处理错误作为对坏数据的响应通常不是最好的策略。更少的控制(正如您在这里看到的)和异常非常缓慢。是的,“插入前检查”对我来说也是正确的。谢谢,我真的很感激……“插入前检查”的问题是,它需要两次往返服务器,在中间,它会受到竞争条件的影响。只需插入约束并等待约束爆炸就可以解决这两个问题,代价是当影响多行时,无法轻松区分哪一行是重复的。@Alejandro没错,这是另一种权衡。这两种方法我都见过,也都做过,每种方法在我的经验中都有自己的位置。不过,您可以在一个非常小的操作中使用MERGE进行检查,但对于较小的故障率来说,这可能会稍微慢一点。这场比赛是可以通过各种方式解决的,你当然知道,但这也有一些(小的)缺点。。。我是否可以通过这种方式检测发生在哪个列上的冲突?