SELECT IDENT_CURRENT(tableName)和自增长列的纠结

 项目中要用到一个功能:主表主键为自增长,要求在插入主表数据前先获得主表要插入数据的主键ID值,用在插入子表时获取主键ID。在网上搜了一下,发现SELECT IDENT_CURRENT(TableName)这个语句可以实现。可是后来发现这个语句存在一个致命问题。

 

问题如下:(表中数据都为空)

(情况一)

当新建表数据为空时, IDENT_CURRENT(TableName)返回值为1.这时主表数据插入成功后,主表自增长列会自动赋值

(情况二)

   当新增一条数据并删除后, IDENT_CURRENT(TableName)返回值还是1,可是现在主表插入成功后,主表自增长列会自动赋值2,而插入子表的主表ID还是1,这样就会导致主表和子表的关联字段不一致。

 

  在网上找了几个解决方案:

1.     DBCC CHECKIDENT (tableName, RESEED, 1)

重置表的标示种子为1,可是在‘情况二’下,数据库还是会以 2 赋给主表ID字段,而不是1

2.     DBCC CHECKIDENT (tableName)

情况一下输出为:

检查标识信息: 当前标识值'null',当前列值'null'

情况二下输出为:

检查标识信息: 当前标识值'1',当前列值'1'

虽然根据输出信息不同,当数据表空时可以判断是‘情况一’还是‘情况二’,可是在C#中无论用ExecuteNonQuery, ExecuteScalar还是datatable返回的都是空数据

 

    郁闷了一个下午始终没有找到答案,最后发现用下面的方法可以实现在子表中插入主表最新记录的ID值。 直接将CONVERT(INT,IDENT_CURRENT('SalesInfo'))作为主键ID的值添加到子表sql语句即可

INSERT INTO PayInfo(SID) VALUES(CONVERT(INT,IDENT_CURRENT('STable')))

 

 

posted @ 2010-03-18 17:21 阅读(1682) 评论(9) 编辑 收藏

 回复 引用 查看   
#1楼2010-03-18 18:36 | 木鱼      
为啥不在插入成功后用 SCOPE_IDENTITY() 查询生成的主键呢?
 回复 引用 查看   
#2楼[楼主]2010-03-18 18:45 |       
引用木鱼:为啥不在插入成功后用 SCOPE_IDENTITY() 查询生成的主键呢?

主表和子表插入要放在同一个事务中

 回复 引用 查看   
#3楼2010-03-18 18:51 | 木鱼      
引用扯:
引用木鱼:为啥不在插入成功后用 SCOPE_IDENTITY() 查询生成的主键呢?

主表和子表插入要放在同一个事务中


即便是有事务,事务没有提交的情况下,只要上一个插入操作正确执行了, SCOPE_IDENTITY() 也是正确返回的

 回复 引用 查看   
#4楼2010-03-18 21:16 | 2008年的梦想      
引用木鱼:
引用扯:
引用木鱼:为啥不在插入成功后用 SCOPE_IDENTITY() 查询生成的主键呢?

主表和子表插入要放在同一个事务中


即便是有事务,事务没有提交的情况下,只要上一个插入操作正确执行了, SCOPE_IDENTITY() 也是正确返回的

言之有理。

 回复 引用 查看   
#5楼2010-03-18 21:49 | 木鱼      
@2008年的梦想
嗨..我就是这么一说,不过你文中提到的那个函数我还真没用过,长见识了

 回复 引用 查看   
#6楼[楼主]2010-03-18 22:23 |       
【情况一】和【情况二】下主表数据都为空,可是IDENT_CURRENTfan
引用2008年的梦想:
引用木鱼:
引用扯:
引用木鱼:为啥不在插入成功后用 SCOPE_IDENTITY() 查询生成的主键呢?

主表和子表插入要放在同一个事务中


即便是有事务,事务没有提交的情况下,只要上一个插入操作正确执行了, SCOPE_IDENTITY() 也是正确返回的

言之有理。


我试了SCOPE_IDENTITY(),也会导致【情况一】和【情况二】的问题,数据为空或只有一条的时候返回的都是1

 回复 引用 查看   
#7楼2010-03-18 22:32 | 阿滨       
用事务 然后用SCOPE_IDENTITY肯定没问题
 回复 引用 查看   
#8楼2010-03-19 16:04 | blackcat      
我觉得需要这么实现的话,设计是不是又不合适的地方?
 回复 引用 查看   
#9楼2010-04-14 10:06 | 莫慌      
要求在插入主表数据先获得主表要插入数据的主键ID值,用在插入子表时获取主键ID

这个设计明显有问题,既然是自动增长的,怎么可能在没有插入就获得值呢
而INSERT INTO PayInfo(SID) VALUES(CONVERT(INT,IDENT_CURRENT('STable')))
这句之所以正确是因为在插入到PayInfo之前先执行了插入'STable'的动作,自然用IDENT_CURRENT就能得到你想要的值了