将 sql 2000 备份恢复到 sql 2008 后,使用 IDENTITY 列的过程因主键冲突而失败
我刚刚将数据库从 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 列(例如本例中的somethingId)是一个带有主键的IDENTITY(1,1),并且这些表中有很多行。
恢复到 SQL 2008 实例后,我的许多数据库似乎工作正常,但类似的调用会
exec usp_add_something @somethingId = -1, @somethingName = 'A Name'
导致如下错误:
违反主键约束“Something_PK”。无法在对象“dbo.something”中插入重复的键。
似乎有些事情搞砸了,导致 SQL Server 无法正确分配下一个 IDENTITY...或类似的情况。这很奇怪!
我可以直接 INSERT 到表中,而无需指定 id 列,并且它会为标识列分配一个 id 。
没有 SomethingId = -1 的记录...但这并不会有任何区别。
如果我删除并重新创建该过程,问题就会消失。但我有很多这样的过程,所以不想这样做,以防万一我错过了一些过程,或者数据库中有一个自定义过程被我覆盖。
有谁知道与此相关的任何已知问题? (以及理想的解决方案!)
是否有其他方法可以将我的 sql 2000 数据库移动到 sql 2008 实例?例如,Detach 和 Attach 的行为是否可能不同?
我尝试使用 sp_recompile 'usp_add_something' 重新编译该过程,但这并没有解决问题,所以我不能简单地在所有过程上调用它。
感谢您的任何帮助
R
(交叉发布 此处)
I've just moved a database from a SQL 2000 instance to a SQL 2008 instance and have encountered an odd problem which appears to be related to IDENTITY columns and stored procedures.
I have a number of stored procedures in the database along the lines of this
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
These are all created as ENCRYPTED stored procedures. The id column (e.g. somethingId in this example) is an IDENTITY(1,1) with a PRIMARY KEY on it, and there are lots of rows in these tables.
Upon restoring onto the SQL 2008 instance a lot of my database seems to be working fine, but calls like
exec usp_add_something @somethingId = -1, @somethingName = 'A Name'
result in an error like this:
Violation of PRIMARY KEY constraint 'Something_PK'. Cannot insert duplicate key in object 'dbo.something'.
It seems that something is messed up that either causes SQL Server to not allocate the next IDENTITY correctly...or something like that. This is very odd!
I'm able to INSERT into the table directly without specifying the id column and it allocates an id just fine for the identity column.
There are no records with somethingId = -1 ... not that that should make any difference.
If I drop and recreate the procedure the problem goes away. But I have lots of these procedures so don't really want to do that in case I miss some or there is a customized procedure in the database that I overwrite.
Does anyone know of any known issues to do with this? (and a solution ideally!)
Is there a different way I should be moving my sql 2000 database to the sql 2008 instance? e.g. is it likely that Detach and Attach would behave differently?
I've tried recompiling the procedure using sp_recompile 'usp_add_something' but that didn't solve the problem, so I can't simply call that on all procedures.
thanks for any help
R
(cross-posted here)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果问题是身份种子设置不正确,您可以通过以下方式重置表:
这将自动查找表中的最高值并适当设置种子,因此您不必执行 SELECT Max()< /代码> 查询。现在修复表可以自动化完成,无需动态 SQL 或手动编写脚本。
但你说你可以直接插入到表中没有问题,所以这可能不是问题。但我想发帖澄清重置身份种子的简单方法。
注意:如果您的表格增量为负数,或者您过去重置种子以在消耗完所有正数后从最低的开始用完所有负数,则所有投注均无效。特别是在后一种情况下(具有正增量,但您使用的标识值低于表中已有的其他值),则您不想运行
DBCC CHECKIDENT
code> 而不指定
NORESEED
曾经。因为仅仅
DBCC CHECKIDENT (TableName);
就会搞砸您的身份值。您必须使用DBCC CHECKIDENT (TableName, NORESEED)
。如果你忘记了这一点,有趣的时光就会随之而来。 :)If the problem is an improperly set identity seed, you can reset a table this way:
This will automatically find the highest value in the table and set the seed appropriately so you don't have to do a
SELECT Max()
query. Now fixing the table can be done in automation, without dynamic SQL or manual script writing.But you said you can insert to the table directly without a problem, so it's probably not the issue. But I wanted to post to set the record straight about the easy way to reset the identity seed.
Note: if your table's increment is negative, or you in the past reset the seed to use up all negative numbers starting at the lowest after consuming all the positive numbers, all bets are off. Especially in the latter case (having a positive increment, but you are using identity values lower than others already in the table), then you do not want to run
DBCC CHECKIDENT
without specifyingNORESEED
ever. Because justDBCC CHECKIDENT (TableName);
will screw up your identity value. You must useDBCC CHECKIDENT (TableName, NORESEED)
. Fun times will ensue if you forget this. :)首先,检查表中的最大 ID:
然后,检查当前身份种子:
如果当前种子低于最大值,请使用 dbcc checkident 为表重新设定种子:
其中 42 是当前最大值。
有关如何出错的演示代码:
First, check the maximum ID from your table:
Then, check the current identity seed:
If the current seed is lower than the maximum, reseed the table with
dbcc checkident
:Where 42 is the current maximum.
Demonstration code for how this can go wrong:
我尝试过,但无法在另一台服务器上复制此内容。
然而,在我的实时服务器上,我从 sql 2008 中删除了有问题的数据库,并使用分离和重新附加重新创建了它,这工作很好,没有这些主键违规错误。
由于我想让原始数据库保持活动状态,实际上我的具体步骤是:
在同一实例上备份 sourceDb 并恢复为 sourceDbCopy
take sourceDbCopy 离线
将sourceDbCopy 文件移动到新服务器
附加数据库
重命名数据库改为原来的名称
I tried and was unable to replicate this on another server.
However, on my Live servers I dropped the problem database from sql 2008 and recreated it using a detach and reattach and this worked fine, without these PRIMARY KEY VIOLATION errors.
Since I wanted to keep the original database live, in fact my exact steps were:
back up sourceDb and restore as sourceDbCopy on the same instance
take sourceDbCopy offline
move the sourceDbCopy files to the new server
attach the database
rename the database to the original name
如果重新创建程序有帮助,这里有一个生成重新创建脚本的简单方法:
If recreating the procedures helps, here's an easy way to generate a recreation script: