在select语句中违反PRIMARY KEY

时间:2010-01-11 15:00:20

标签: sql sql-server sql-server-2005

我有一个看起来像这样的表:

CREATE TABLE [dbo].[SomeTable](
    [Guid] [uniqueidentifier] NOT NULL,
    [Column1] [int] NOT NULL,
    [Column2] [datetime] NOT NULL,
    [Column3] [bit] NOT NULL,
    [Column4] [smallint] NOT NULL,
    [Column5] [uniqueidentifier] NULL,
    [Column6] [varchar](100) NULL,
    [Column7] [datetime] NULL,
    [Column8] [datetime] NULL,
 CONSTRAINT [pkSomeTable] PRIMARY KEY CLUSTERED 
(
    [Guid] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 80) ON [PRIMARY]
)

注意:名称已更改以保护无辜者。

通过存储过程,我正在运行此查询:

SELECT SomeTable.Guid, SomeTable.Column1, SomeTable.Column2, SomeTable.Column3, SomeTable.Column4, SomeTable.Column5, SomeTable.Column6, SomeTable.Column7, SomeTable.Column8
        FROM SomeTable
        WHERE SomeTable.Guid = @Guid 
        ORDER BY SomeTable.Guid

运行之后,我得到一个: 违反PRIMARY KEY约束'pkSomeTable'。无法在对象'dbo.SomeTable'中插入重复键。  UniqueKeyConstraintException:重复键。

我很困惑我如何能够像这样只运行一个select语句。桌子上没有触发器。有没有人知道如何发生这种情况?

编辑: 整个stp是:

    CREATE PROCEDURE dbo.stpSelectSomeTable
        @Guid UNIQUEIDENTIFIER = NULL
    AS
    BEGIN
    SET NOCOUNT ON

    IF  (@Guid is NULL) 

         SELECT SomeTable.Guid, SomeTable.Column1, SomeTable.Column2, SomeTable.Column3, SomeTable.Column4, SomeTable.Column5, SomeTable.Column6, SomeTable.Column7, SomeTable.Column8
        FROM SomeTable
        ORDER BY SomeTable.Guid

    Else

         SELECT SomeTable.Guid, SomeTable.Column1, SomeTable.Column2, SomeTable.Column3, SomeTable.Column4, SomeTable.Column5, SomeTable.Column6, SomeTable.Column7, SomeTable.Column8
        FROM SomeTable
        WHERE SomeTable.Guid = @Guid 
        ORDER BY SomeTable.Guid

END
GO

我确信在调用此STP时GUID不为null。我也确定这是导致问题的陈述。异常的堆栈跟踪向我展示了这一点。事实证明,发生这种情况的数据库已被删除并恢复到以前的版本。因此,我无法测试声明。这是在给我这个问题之前完成的。

4 个答案:

答案 0 :(得分:3)

我刚尝试了你上面发布的SQL并且没有违反PK,正如其他人所指出的那样,该语句本身没有问题所以它必须在其他地方。

至于如何解决问题,您可以尝试使用SQL事件探查器创建跟踪然后运行SP。这应该可以帮助您找出导致PK违规的语句发生的位置。您需要安装SQL事件探查器才能使用此功能。这是一个链接以获取更多信息: http://technet.microsoft.com/en-us/library/ms175047.aspx

答案 1 :(得分:2)

我怀疑你误解了SQL错误消息,它告诉你它检测到错误的行。

行号将相对于发生错误的查询批处理的START。 GO用作批处理分隔符。因此,以下示例中INSERT上的PK错误将报告为在第1行发生。

/*A comment
Next line starts a new batch*/
GO
INSERT INTO T1 VALUES(1)

大多数情况下,评论不对PK违规行为负责。

修改 要追踪问题,请通过评论不相关的部分来运行脚本“吃饭”的部分内容。

答案 2 :(得分:1)

另一个想法......你确定那是你正在调用的存储过程吗?

SQL Server有一些可能导致混淆的事情。例如:单个数据库可以有多个“模式”。如果你没有使用约定来调用你的存储过程,你最终可能会从不同的模式中调用一个同名的proc。

我建议你修改你的存储过程以打印一个简单的输出行来确认那是被调用的那个。

答案 3 :(得分:0)

看起来问题实际上是一个插入。不确定为什么错误选择了导致问题的语句。这是一个线程问题。我们有这样的代码:

row = dbo.stpSelectSomeTable @Guid = {SomeGuid}
if (row exists)
{
  do stuff to update the row
}
else
{
  insert new row with {SomeGuid}
}

这里没有任何类型的同步,因此多个线程试图插入具有相同guid的行。我们加了一把锁,一切都很好。

感谢所有人的建议。