2010-01-11 76 views
2

主键我有一个表,看起来像这样:违反了select语句

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:重复键。

我很困惑我如何能有这样的异常只运行一个选择语句。桌子上没有触发器。有没有人有这样的想法?

编辑: 整个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 

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

+1

双重和三重检查导致PK违规的声明。 是什么让你认为这是SELECT语句? – 2010-01-11 15:04:30

+3

您确定此声明导致错误?您能否单独运行此声明以查看问题是否存在?你能不能发布整个sproc源代码? – Quassnoi 2010-01-11 15:04:36

+0

存储过程还有什么作用?你可以显示存储过程的所有代码,以及你如何调用它? – 2010-01-11 15:08:29

回答

2

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

行号将相对于发生错误的查询批处理的开始。 GO用作批量分离器。因此,具有1行

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

发生了下面的例子在INSERT一个PK错误将被报告为大多数肯定的评论是不负责的PK违反。

编辑 要跟踪问题,可以通过注释掉不相关的部分来运行脚本“零食”部分。

+0

我正在谈论C#应用程序中的堆栈跟踪。它与SQL Server报告的行号没有任何关系。 – Bryan 2010-01-11 15:25:11

+0

在这种情况下,我建议您运行SQL Server Profiler来检查正在执行的查询/ procs。 C#正在拾取错误,但是其他内容正在导致错误。 – 2010-01-11 15:35:19

3

我刚刚尝试过上面发布的SQL,没有违反PK的规定,所以别人指出,这个语句本身没有问题,所以它必须在其他地方。

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

1

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

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

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

+0

我们总是用dbo调用存储过程。前缀。虽然好想。 – Bryan 2010-01-11 15:34:05

0

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

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

有没有任何形式的同步这里,所以多个线程试图插入一行具有相同GUID的。我们加了一把锁,一切都很好。

非常感谢您的建议。

+0

其他答案告诉你SELECT不会导致PK违规?你为什么不接受其中之一? – 2010-01-22 08:16:20