4

我遇到了一个奇怪的问题,我需要一些帮助来解决这个问题。

我有一个数据库,除了所有应用程序数据列之外,它还有一个 ID 列(定义为 int not null,Identity,从 1 开始,递增 1)。该表的主键是 ID 列,没有其他组件。

没有一组数据可以用作“自然主键”,因为应用程序必须允许多次提交相同的数据。

我有一个存储过程,这是将新记录添加到表中的唯一方法(除了直接以数据库所有者身份登录服务器)

今天早上 QA 测试应用程序时,他们在数据库中输入了一条新记录(按预期使用应用程序,并且正如他们过去两周一直在做的那样),并在该表上遇到了主键冲突。

这与我 10 年来一直在做主键的方式相同,但从未遇到过这种情况。

有想法该怎么解决这个吗?或者这是那些偶尔出现的宇宙射线故障之一。

感谢您提供的任何建议。

奈杰尔

编辑于美国东部时间 6 月 12 日下午 1:15,以提供更多信息

架构的简化版本...

CREATE TABLE [dbo].[tbl_Queries](
[QueryID] [int] IDENTITY(1,1) NOT NULL,
[FirstName] [varchar](50) NOT NULL,
[LastName] [varchar](50) NOT NULL,
[Address] [varchar](150) NOT NULL,
[Apt#] [varchar](10) NOT NULL
    ... <12 other columns deleted for brevity>
[VersionCode] [timestamp] NOT NULL,
 CONSTRAINT [PK_tbl_Queries] PRIMARY KEY CLUSTERED 
(
    [QueryID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

(还删除了默认值语句)

存储过程如下

insert into dbo.tbl_Queries
    (   FirstName,
        LastName,
        [Address],
        [Apt#]...) values
    (   @firstName,
        @lastName,
        @address,
        isnull(@apt, ''), ... )

它甚至不看身份列,不使用 IDENTITY、@@scope_identity 或类似的东西,它只是一个文件,然后忘记。

我尽可能确信身份值没有被重置,并且没有其他人使用直接数据库访问来输入值。在这个项目中唯一一次使用身份插入是在初始数据库部署中设置查找表中的特定值。

QA 团队在收到错误后立即再次尝试,并且能够成功提交查询,此后他们一直在尝试重现它,但到目前为止还没有成功。

我真的很欣赏这些想法。

4

8 回答 8

6

听起来身份种子以某种方式损坏或重置。最简单的解决方案是将种子重置为标识列的当前最大值:

DECLARE @nextid INT;
SET @nextid = (SELECT MAX([columnname]) FROM [tablename]);
DBCC CHECKIDENT ([tablename], RESEED, @nextid);
于 2009-06-12T14:47:50.443 回答
4

虽然我没有解释潜在原因,但确实可以更改标识列的种子值。如果种子被降低到表中已经存在下一个值的位置,那么这肯定会导致您所看到的。尝试跑步DBCC CHECKIDENT (table_name),看看它会给你什么。

有关更多信息,请查看此页面

于 2009-06-12T14:46:17.437 回答
1

基于经验的随机想法

您是否与 Red Gate Data Compare 同步数据。这有一个重新设定身份列的选项。导致使用问题。上个月还有另一个项目。

您也可能有明确加载/同步的 ID。

于 2009-06-12T14:44:27.830 回答
0

主键违规不一定来自该表。

应用程序是否接触任何其他表或为该函数调用任何其他存储过程?桌子上有触发器吗?或者存储过程本身是否使用任何其他表或存储过程?

特别是,审计表或触发器可能会导致这种情况。

于 2009-06-12T17:36:21.677 回答
0

也许有人直接使用新的 ID 直接将一些记录插入到服务器中,然后当身份自动递增字段达到这个数字时,就会发生主键冲突。

但是宇宙射线是一个很好的解释;)

于 2009-06-12T14:48:13.487 回答
0

只是为了非常非常确定......您没有在存储过程中使用 IDENTITY_INSERT 是吗?像这样的一些逻辑:

declare @id int;
Set @id=Select Max(IDColumn) From Sometable;
SET IDENTITY_INSERT dbo.SomeTable ON
Insert (IDColumn, ...others...) Values (@id+1, ...others...);
SET IDENTITY_INSERT dbo.SomeTable OFF
.
.
.

我只是打字感觉很粘。但是每隔一段时间,你就会遇到那些从来没有完全理解过身份专栏的人,我想确保这被排除在外。顺便说一句:如果这是答案,如果只是删除问题并且永远不承认这是你的问题,我不会反对你!

你能说我每年夏天都会招实习生吗?

于 2009-06-12T14:50:18.910 回答
0

您是否在任何程序中使用 @@identity 或 scope_identity() 之类的函数?如果您的表有触发器或多个插入,您可能会为您想要的表取回错误的标识值

于 2009-06-12T15:02:17.943 回答
0

希望情况并非如此,但在 SQL 2005 中存在一个已知错误,带有 SCOPE_IDENTITY(): http ://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=328811

于 2009-06-12T15:11:50.947 回答