SQL Server 2008 R2中的标识规范

时间:2014-05-02 17:47:03

标签: sql sql-server sql-server-2008 sql-server-2008-r2

我在SQL Server中有一个名为Personal_Info的表。该表有一个名为Vol_ID的列,(Is Identity)属性为Yes

现在我插入了大约175568行作为测试。然后我删除了大约568行,但是当我再次插入数据时,列Vol_ID从175569开始而不是从175001开始。

我想插入数据,让列Vol_ID从其中的最后一个数字开始。例如,如果最后一行是15,则下一行应该从16开始,即使我已经插入但是我将其删除。

我需要一个存储过程或触发器,它可以强制插入操作填充缺少的id,检查最后存在的行,如果在存在之后缺少id,则填充它。

我有这个程序来插入

  USE [VolunteersAffairs] 

go 

/****** Object:  StoredProcedure [dbo].[AddVolunteer]    Script Date: 05/02/2014      21:12:36 ******/ 
SET ansi_nulls ON 

go 

SET quoted_identifier ON 

go 

ALTER PROCEDURE [dbo].[Addvolunteer] @Vol_Name                 NVARCHAR(255), 
                                     @Vol_Zone                 NVARCHAR(255), 
                                     @vol_street               NVARCHAR(255), 
                                     @Vol_Sex                  INT, 
                                     @Vol_Date_of_Birth        DATE, 
                                     @Vol_Home_Phone           INT, 
                                     @Vol_Work_Phone           INT, 
                                     @Vol_Mobile1              INT, 
                                     @Vol_Mobile2              INT, 
                                     @Vol_Email                NVARCHAR(255), 
                                     @Vol_Job                  NVARCHAR(255), 
                                     @Vol_Affiliation          NVARCHAR(255), 
                                     @vol_Education            INT, 
                                     @vol_Education_Place      NVARCHAR(255), 
                                     @vol_Education_Department NVARCHAR(255), 
                                     @vol_Interesting          INT, 
                                     @vol_Notes                NVARCHAR(255), 
                                     @Team_ID                  INT 
AS 
    INSERT INTO personal_info 
                (vol_name, 
                 vol_zone, 
                 vol_street, 
                 vol_sex, 
                 vol_date_of_birth, 
                 vol_home_phone, 
                 vol_work_phone, 
                 vol_mobile1, 
                 vol_mobile2, 
                 vol_email, 
                 vol_job, 
                 vol_affiliation, 
                 vol_education, 
                 vol_education_place, 
                 vol_education_department, 
                 vol_interesting, 
                 team_id, 
                 vol_notes) 
    VALUES      (@Vol_Name, 
                 @Vol_Zone, 
                 @vol_street, 
                 @Vol_Sex, 
                 @Vol_Date_of_Birth, 
                 @Vol_Home_Phone, 
                 @Vol_Work_Phone, 
                 @Vol_Mobile1, 
                 @Vol_Mobile2, 
                 @Vol_Email, 
                 @Vol_Job, 
                 @Vol_Affiliation, 
                 @vol_Education, 
                 @vol_Education_Place, 
                 @vol_Education_Department, 
                 @vol_Interesting, 
                 @Team_ID, 
                 @vol_Notes) 

请帮我写下遗失的身份证明

4 个答案:

答案 0 :(得分:2)

您需要重新设置标识列,如下所示

DBCC CHECKIDENT(Personal_Info, RESEED, 175001)

引自MSDN

  

许可:

     

调用者必须拥有该表,或者是sysadmin固定服务器的成员   角色,db_owner固定数据库角色或db_ddladmin已修复   数据库角色。

因此。它是表的所有者(OR)DBA可以执行标识列的reseed而不是普通用户。此外,为什么您甚至允许您的应用程序用户重新设置标识列值?这根本没有意义。

修改

在那种情况下,请查看下面的@Brennan回答。简而言之,您应该从存储过程执行插入。我的意思是你的APP应该调用SP并执行插入。如下(示例代码)。此外,在这种情况下,删除vol_id列的标识属性(vol_id应该只是vol_id int not null unique

create procedure sp_insert-person
@name varchar(10)
as 
begin
declare @last_id int;
select @last_id = top 1 Vol_ID from Personal_Info order by Vol_ID desc;
insert into Personal_Info(Vol_ID,name) 
values(@last_id+1,@name);
end

您的应用程序将调用此程序

exec sp_insert-person @name = 'user2251369'

最终编辑:

请参阅此帖子RESEED identity columns on the database,了解为什么要避免reseeding IDENTITY值(由marc_s给出的一个很好的小解释)。

您的最终程序应如下所示

USE [VolunteersAffairs]
GO
/****** Object:  StoredProcedure [dbo].[AddVolunteer]    
 Script Date: 05/02/2014      21:12:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[AddVolunteer]
@Vol_Name nvarchar(255), 
@Vol_Zone nvarchar(255), 
@vol_street nvarchar(255), 
@Vol_Sex int, 
@Vol_Date_of_Birth date, 
@Vol_Home_Phone int, 
@Vol_Work_Phone int, 
@Vol_Mobile1 int,    
@Vol_Mobile2 int, 
@Vol_Email nvarchar(255), 
@Vol_Job nvarchar(255), 
@Vol_Affiliation nvarchar(255), 
@vol_Education int, 
@vol_Education_Place nvarchar(255), 
@vol_Education_Department nvarchar(255), 
@vol_Interesting int, 
@vol_Notes nvarchar(255), 
@Team_ID int
As
BEGIN
DECLARE @last_vol_id int;
select top 1 @last_vol_id = Vol_ID from Personal_Info order by Vol_ID desc;

insert into Personal_Info
(Vol_Id,
Vol_Name, 
Vol_Zone, 
vol_street, 
Vol_Sex, 
Vol_Date_of_Birth, 
Vol_Home_Phone, 
Vol_Work_Phone, 
Vol_Mobile1, 
Vol_Mobile2, 
Vol_Email, 
Vol_Job, 
Vol_Affiliation, 
vol_Education, 
vol_Education_Place, 
vol_Education_Department, 
vol_Interesting, 
Team_ID, 
vol_Notes) 
values 
(@last_vol_id+1,
@Vol_Name, 
@Vol_Zone, 
@vol_street, 
@Vol_Sex, 
@Vol_Date_of_Birth, 
@Vol_Home_Phone, 
@Vol_Work_Phone, 
@Vol_Mobile1, 
@Vol_Mobile2, 
@Vol_Email, 
@Vol_Job, 
@Vol_Affiliation, 
@vol_Education, 
@vol_Education_Place, 
@vol_Education_Department, 
@vol_Interesting, 
@Team_ID, 
@vol_Notes);
END

答案 1 :(得分:2)

您要做的不是身份列的用途 - 不能保证不会有间隙,删除记录不会重复使用缺少的身份。

如果你真的需要一个顺序的自动增量id字段,没有间隙,那么你最好使用存储过程来进行插入(你需要添加逻辑来重用缺少的id) ,或者定义一个强制执行你想要的触发器 - 但是试图强制标识列执行你想要做的事情是错误的方法。

答案 2 :(得分:0)

正如其他人所说,你可以重新定位身份。但是,这只有在最后删除时才有效。填补身份的空白将是非常具有挑战性的,你最终将不得不关闭身份。

如果这是种子数据的小例子,您可以打开身份插入。 enter link description here

SET IDENTITY_INSERT {your table} ON

Here is another question highlighting the other concerns

答案 3 :(得分:0)

这是神奇的。在插入之前执行此操作。

declare @i int
select @i=max(id) from Personal_Info
DBCC CHECKIDENT (Personal_Info, RESEED, @i)