Нарушение ПЕРВИЧНОГО КЛЮЧА при выборе заявления - PullRequest
2 голосов
/ 11 января 2010

У меня есть таблица, которая выглядит так:

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: дубликат ключа.

Я очень озадачен тем, как у меня может быть исключение, подобное этому, выполняющее только оператор выбора. На столе нет триггеров. У кого-нибудь есть идеи о том, как это может произойти?

Edit: Весь 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. Я также уверен, что это утверждение вызвало проблему. Трассировка стека исключения показывает мне это. Оказывается, база данных, в которой это произошло, была удалена и восстановлена ​​в предыдущей версии. Из-за этого я не могу проверить утверждение. Это было сделано до того, как этот вопрос был передан мне.

Ответы [ 4 ]

3 голосов
/ 11 января 2010

Я только что попробовал SQL, который вы опубликовали выше, и не получил никакого нарушения PK, поэтому, как отмечали другие, с этим утверждением нет никаких проблем, поэтому оно должно быть где-то еще.

Что касается решения проблемы, вы можете попытаться использовать профилировщик SQL для создания трассировки, а затем запустить SP. Это должно помочь вам выяснить, где происходит утверждение, которое вызывает нарушение PK. Вам необходимо установить SQL Profiler для использования этой функции. Вот ссылка для получения дополнительной информации: http://technet.microsoft.com/en-us/library/ms175047.aspx

2 голосов
/ 11 января 2010

Я подозреваю, что вы неверно истолковали сообщение об ошибке SQL, в котором указана строка, в которой обнаружена ошибка.

Номер строки будет относительно START пакета запроса, в котором произошла ошибка. GO используется в качестве разделителя партий. Таким образом, в следующем примере ошибка PK на INSERT будет сообщаться как произошедшая в строке 1.

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

Скорее всего, комментарий не несет ответственности за нарушение PK.

Редактировать Чтобы отследить проблему, запустите разделы сценария «по частям», закомментировав ненужные разделы.

1 голос
/ 11 января 2010

Еще одна мысль ... вы уверены, что это сохраненный процесс, которому вы звоните?

В SQL Server есть несколько вещей, которые могут вызвать путаницу. Например: одна база данных может иметь несколько «схем». Если вы не вызываете свой сохраненный процесс с использованием соглашения., Вы можете в конечном итоге вызвать процесс с тем же именем из другой схемы.

Я предлагаю вам изменить свой сохраненный процесс, чтобы напечатать простую строку вывода, чтобы подтвердить, что именно она была вызвана.

0 голосов
/ 20 января 2010

Похоже, проблема была в вставке. Не уверен, почему ошибка была выбрана в качестве утверждения, вызвавшего проблему. Это была проблема с потоками. У нас был такой код:

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

Здесь не было никакой синхронизации, поэтому более одного потока пытались вставить строку с одинаковым guid. Мы добавили замок, и все было хорошо.

Спасибо всем за ваши предложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...