我有一个SQL Server表定义为
CREATE TABLE [dbo].[Products]
(
[ProductId] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (50) NOT NULL,
[Description] NVARCHAR (400) NOT NULL,
[Category] NVARCHAR (50) NOT NULL,
[Price] DECIMAL (18) NOT NULL,
PRIMARY KEY CLUSTERED ([ProductId] ASC)
);
现在我的问题是我之前在表格中存储了7个项目,ID依次从1到7开始,当我在表格中添加新产品时,ID会自动获得一个随机值,如1016,然后是另一个新项目item它获得值1017,依此类推。如何设置ID值以便自动检测上次存储的ID并自动在该值中递增1?
答案 0 :(得分:2)
您的标识列生成的值应该无关紧要。
如果您的代码或应用程序依赖于从Identity列生成的值,那么您应该真正修复该逻辑。
根据MSDN标识值保证是增量和顺序的,但不能保证它们是否是连续值。特别是在SQL Server 2012中,它往往会有大幅度的跳跃,例如100到1000。
无论如何,要将Identity列重新设置为下一个可用的最高值,您可以执行以下操作。
-- Reseed to any lowest value say 0
DBCC CHECKIDENT ('[dbo].[Products]', RESEED , 0)
GO
-- Execute the same command but this time without any seed value
DBCC CHECKIDENT ('[dbo].[Products]', RESEED)
GO
这会将您的标识列重新设置为标识列中的下一个最高可用值。
答案 1 :(得分:1)
您可以像这样重置身份种子:
DECLARE @cmd VARCHAR(MAX)
SELECT 'DBCC CHECKIDENT (''[dbo].[Products]'', RESEED, '+(CAST(MAX(id)+1 AS VARCHAR(MAX)))+');' FROM [dbo].[Products]
-- PRINT @cmd
EXEC(@cmd)
你必须考虑如果你需要一个没有任何漏洞的清晰的id序列,IDENTITY将无法给你这个。如果插入行的事务将被回滚,那么IDENTITY将保持递增并且将出现新的孔。
答案 2 :(得分:1)
我对您创建表格的方式以及我对您的要求的理解有两个问题:
如果您需要连续递增没有间隙的行,则不应使用标识列。它并不保证。并试图重新选择它以填补空白是一个坏主意。最好问你自己,你真的需要它是顺序的。如果答案为是,那么您必须以编程方式在处理此表的INSERT的存储过程中实现它。我个人没有看到原因。另一个需要考虑的重要事项是,如果使用ID列将此表引用到其他表中。
您正在使用ID列和PK列,我没有看到在自然列上创建的任何其他唯一索引。因此,SQL Server不会阻止您插入两个或多个具有相同名称的产品(实际上该表中的每个列都相同)具有不同的ID。你被迫以编程方式处理这个问题。如果你依赖这个表每个产品有一行,那么模式本身并不能阻止任何人插入重复项。一个简单的解决方法是在业务键上创建唯一索引,使行唯一(名称+类别)。