Процедуры, использующие столбец IDENTITY, завершаются с ошибкой первичного ключа после восстановления резервной копии SQL 2000 на SQL 2008 - PullRequest
4 голосов
/ 21 июля 2010

Я только что переместил базу данных из экземпляра SQL 2000 в экземпляр SQL 2008 и обнаружил странную проблему, которая, по-видимому, связана со столбцами IDENTITY и хранимыми процедурами.

У меня есть ряд сохраненныхпроцедуры в базе данных в соответствии с этими

create procedure usp_add_something @somethingId int, @somethingName nvarchar(100)
with encryption
as

-- If there's an ID then update the record
if @somethingId <> -1 begin

 UPDATE  something  SET somethingName = @somethingName

end else begin

 -- Add a new record
 INSERT INTO something ( somethingName )  VALUES ( @somethingName )

end

go

Все они созданы как зашифрованные хранимые процедуры.Столбец id (например, SomeId в этом примере) - это IDENTITY (1,1) с ПЕРВИЧНЫМ КЛЮЧОМ на нем, и в этих таблицах много строк.

При восстановлении на экземпляр SQL 2008 многомоей базы данных, кажется, работает нормально, но вызовы типа

exec usp_add_something @somethingId = -1, @somethingName = 'A Name'

приводят к ошибке, подобной этой:

Violation of PRIMARY KEY constraint 'Something_PK'. Cannot insert duplicate key in object 'dbo.something'.

Кажется, что-то запутаноэто либо приводит к тому, что SQL Server неправильно распределяет следующую IDENTITY ... или что-то в этом роде.Это очень странно!

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

Нет записей с someId= -1 ... не то, чтобы это имело какое-либо значение.

Если я уроню и заново создам процедуру, проблема исчезнет.Но у меня есть много таких процедур, поэтому я не хочу этого делать в случае, если я пропущу некоторые или в базе данных будет настроенная процедура, которую я перезаписываю.

Кто-нибудь знает какие-либо известные проблемы, связанные сэтот?(и решение в идеале!)

Есть ли другой способ перенести мою базу данных sql 2000 в экземпляр sql 2008?Например, возможно ли, что Detach и Attach будут вести себя по-разному?

Я попытался перекомпилировать процедуру, используя sp_recompile 'usp_add_something', но это не решило проблему, поэтому я не могу просто вызвать это во всех процедурах

спасибо за любую помощь

R

(кросс-пост здесь )

Ответы [ 4 ]

5 голосов
/ 22 июля 2010

Если проблема связана с неправильно установленным начальным числом идентификаторов, вы можете сбросить таблицу следующим образом:

DBCC CHECKIDENT (TableName, RESEED, 0);
DBCC CHECKIDENT (TableName, RESEED);

Это автоматически найдет самое высокое значение в таблице и установит начальное значение соответствующим образом, чтобы вам не нужно было делать запрос SELECT Max(). Теперь исправление таблицы может быть выполнено автоматически, без динамического SQL или написания сценария вручную.

Но вы сказали, что можете вставлять в таблицу напрямую без проблем, так что, вероятно, это не проблема. Но я хотел опубликовать, чтобы установить рекорд о простом способе сброса идентификационного семени.

Примечание: если приращение вашей таблицы отрицательное или вы в прошлом сбрасывали начальное число, чтобы использовать все отрицательные числа, начиная с самого низкого после использования всех положительных чисел, все ставки отключены . Особенно в последнем случае (с положительным приращением, но вы используете значения идентификаторов ниже , чем другие, уже присутствующие в таблице), тогда вы не хотите запускать DBCC CHECKIDENT без указания NORESEED никогда . Потому что просто DBCC CHECKIDENT (TableName); испортит вашу личность. Вы должны использовать DBCC CHECKIDENT (TableName, NORESEED). Веселые времена наступят, если вы забудете это. :)

4 голосов
/ 21 июля 2010

Сначала проверьте максимальный идентификатор из вашей таблицы:

select max(id_column) from YourTable

Затем проверьте текущее начальное число:

select ident_seed('YourTable')

Если текущее начальное число меньше максимального, повторно введитетаблица с dbcc checkident:

DBCC CHECKIDENT (YourTable, RESEED, 42)

, где 42 - текущий максимум.

Код демонстрации того, как это может пойти не так:

create table YourTable (id int identity primary key, name varchar(25))
DBCC CHECKIDENT (YourTable, RESEED, 42)
insert into YourTable (name) values ('Zaphod Beeblebrox')
DBCC CHECKIDENT (YourTable, RESEED, 41)
insert into YourTable (name) values ('Ford Prefect') --> Violation of PRIMARY KEY
1 голос
/ 23 июля 2010

Я пытался и не смог скопировать это на другой сервер.

Однако на своих серверах Live я удалил проблемную базу данных из sql 2008 и заново создал ее, используя отсоединение и повторное подключение, и это сработало нормально, без ошибок PRIMARY KEY VIOLATION.

Поскольку я хотел сохранить исходную базу данных, фактически мои точные шаги были такими:

  • резервное копирование sourceDb и восстановление как sourceDbCopy в том же экземпляре

  • перевести sourceDbCopy в автономный режим

  • переместить файлы sourceDbCopy на новый сервер

  • прикрепить базу данных

  • переименовать базу данных в исходное имя

0 голосов
/ 21 июля 2010

Если воссоздание процедур помогает, вот простой способ создания сценария восстановления:

  1. Щелкните правой кнопкой мыши базу данных -> Задачи -> Создать сценарии
  2. На странице 2 («ВыбратьОбъекты ") выберите хранимые процедуры
  3. На странице 3 (" установить параметры сценариев ") выберите" Дополнительно "->" Сценарий DROP и CREATE "и установите для него значение" Сценарий DROP и CREATE ".
  4. Сохраните сценарий где-нибудьи запустить его
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...