请教如何能够根据数据库数目获得连续的序号

jthkl 2016-11-23 06:59:25
一个合同管理程序,想根据合同数目生成合同号,比如第1个合同HT001号,第二个合同HT002,本来希望使用sqlserver数据库的id号,每次增加1,但是发现并不能确保id每次一定+1,有可能跳空若干号,比如100后直接就是1001,详见帖子:http://bbs.csdn.net/topics/392051591。

于是问题就出现了,怎样获得一个连续的合同序号呢?如果直接获得数据个数然后加1,会不会2个人并发操作于是生成两个同样的合同号呢?
不知道大家有没有办法?
...全文
666 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tiger_Zhao 2016-12-20
  • 打赏
  • 举报
回复
#9的先取再更新在多用户下存在取得同一个流水号的可能。
修改一下操作流程
BEGIN TRANSACTION 
BEGIN TRY
-- 直接旧值+1
UPDate SYS_TableAUTOID SET BigEndVAL=BigEndVAL+1 WHERE VarTableName=@NVrTableName AND VarFldName=@NVrFldName
IF @@ROWCOUNT <> 0
BEGIN
-- 如果更新成功,该记录已经被锁住,不会被其它会话更新,获取的新值就是旧值+1
SELECT @BigNextVal=BigEndVAL FROM SYS_TableAUTOID WHERE VarTableName=@NVrTableName AND VarFldName=@NVrFldName
END
ELSE
BEGIN
-- 如果更新不成功,说明主键不存在,则插入值1
INSERT IntO SYS_TableAUTOID (VarTableName,VarFldName,BigEndVAL) VALUES(@NVrTableName,@NVrFldName,1)
-- 如果其它会话先插入,就会有主键重复错误。
-- 本会话插入成功记录也被加锁,新值必定是1
SET @BigNextVal=1
END

COMMIT TRANSACTION
END TRY
jthkl 2016-12-19
  • 打赏
  • 举报
回复
引用 10 楼 MSTOP 的回复:
业务流程。 1。新单时不生成流水号。在保存时才生成。 2。单据不能删除,但可以作废,冲红。
你好,谢谢你的回答。 我想再问一下 在执行 SET @BigNextVal=(ISNULL(@BigNextVal,0) + 1) UPDate SYS_TableAUTOID SET BigEndVAL=@BigNextVal WHERE VarTableName=@NVrTableName AND VarFldName=@NVrFldName 的时候,会不会因为并发而造成的另外一个proc在set和update之间的时间点更改了数据库,造成update的时候最新的流水号已经不是上一句SET @BigNextVal=(ISNULL(@BigNextVal,0) + 1)获得的号码了?
华芸智森 2016-12-12
  • 打赏
  • 举报
回复
业务流程。 1。新单时不生成流水号。在保存时才生成。 2。单据不能删除,但可以作废,冲红。
华芸智森 2016-12-12
  • 打赏
  • 举报
回复


--流水号表。
CREATE TABLE [dbo].[SYS_TableAUTOID](
	[VarTableName] [nvarchar](128) NOT NULL,
	[VarFldName] [nvarchar](64) NOT NULL,
	[BigEndVAL] [bigint] NULL,
 CONSTRAINT [PK_SYS_TableAUTOID] PRIMARY KEY CLUSTERED 
(
	[VarTableName] ASC,
	[VarFldName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

--输出指定表指定字段流水号。
CREATE PROC [dbo].[prc_GetNextAUID] (
    @NVrTableName      NVarChar(128),        --表名
    @NVrFldName        NVarChar(64),        --字段名
    @BigNextVal        BigInt OUTPUT)        --输出流水的下一个值.
AS BEGIN

 BEGIN TRANSACTION 
 BEGIN TRY
    SELECT @BigNextVal=BigEndVAL FROM SYS_TableAUTOID WHERE VarTableName=@NVrTableName AND VarFldName=@NVrFldName
    IF ISNULL(@BigNextVal,0)=0 BEGIN  --将新的标识插入到 SYS_TableAUTOID
        SET @BigNextVal=(ISNULL(@BigNextVal,0) + 1)
        INSERT IntO SYS_TableAUTOID (VarTableName,VarFldName,BigEndVAL) VALUES(@NVrTableName,@NVrFldName,@BigNextVal)
    End    ELSE  BEGIN                    --更新下一个值.
        SET @BigNextVal=(ISNULL(@BigNextVal,0) + 1)
        UPDate SYS_TableAUTOID SET BigEndVAL=@BigNextVal WHERE VarTableName=@NVrTableName AND VarFldName=@NVrFldName 
    End
   COMMIT TRANSACTION
END TRY
BEGIN CATCH
   ROLLBACK TRANSACTION
END CATCH
    RETURN @BigNextVal

End
   


GO
a3212b12 2016-12-05
  • 打赏
  • 举报
回复
引用 7 楼 a3212b12 的回复:
[quote=引用 5 楼 jthkl 的回复:] [quote=引用 4 楼 sp1234 的回复:] 因为只是数据库新手,还处在一条select 混天下的阶段,对锁还没有研究,不知道具体怎样用代码实现,怎样锁住一个表?自己的update会被锁上吗?可以详细写一下代码吗?当当订的书还在路上。。。。还要深入学习啊。
各家数据库,有自己的锁机制,一般都不用考虑锁,你只要在一个事务里面 insert ,然后 select 回来的 id 肯定是最新的。 这里告诉你一个绝对安全的方法,你可以在合同表设个标志列,然后大家可以竞争去设这个标志,然后,这张表就属于这个标志的了,然后你就可以任意处理,处理结束,清空标志,大家又可以竞争。[/quote] 这个标志,其实就是锁了
a3212b12 2016-12-05
  • 打赏
  • 举报
回复
引用 5 楼 jthkl 的回复:
[quote=引用 4 楼 sp1234 的回复:] 因为只是数据库新手,还处在一条select 混天下的阶段,对锁还没有研究,不知道具体怎样用代码实现,怎样锁住一个表?自己的update会被锁上吗?可以详细写一下代码吗?当当订的书还在路上。。。。还要深入学习啊。
各家数据库,有自己的锁机制,一般都不用考虑锁,你只要在一个事务里面 insert ,然后 select 回来的 id 肯定是最新的。 这里告诉你一个绝对安全的方法,你可以在合同表设个标志列,然后大家可以竞争去设这个标志,然后,这张表就属于这个标志的了,然后你就可以任意处理,处理结束,清空标志,大家又可以竞争。
  • 打赏
  • 举报
回复
先给你一个问题思考: 假设在没有电脑的场景下,两个人分别负责开票,两个人如何保证流水号不重复?
  • 打赏
  • 举报
回复
这个的原因 是因为你设置了自动增长的 只有插进去的数据成功就会默认+1 ,你删除了之前的数据,它还是继续原来的基础上+1,因为这个就是为了确定ID的唯一性!!!! 希望能帮到你 其实版主的帖子就是这样,估计你设置了默认增长的话不能连续的 希望大神指点指点怎么做,我也是菜鸟级别 ,待大神出来解决下吧!!!
jthkl 2016-12-02
  • 打赏
  • 举报
回复
引用 4 楼 sp1234 的回复:
先给你一个问题思考: 假设在没有电脑的场景下,两个人分别负责开票,两个人如何保证流水号不重复?
两个人一人一本发票,那样的话唯一号就可以了,不连续。 要么就是开的时候从发票本上撕一张,这样的话相当于把号占上了。 可以弄一个发票表,记录开到哪,查询当前最新发票号,加上1,返回给A,并且把发票表上当前最新发票数更新+1,这个过程中如果能用锁把表锁住,B想查也要等查询结束再查再更新,就能做到号码不重复。不知道我说的对不对? 因为只是数据库新手,还处在一条select 混天下的阶段,对锁还没有研究,不知道具体怎样用代码实现,怎样锁住一个表?自己的update会被锁上吗?可以详细写一下代码吗?当当订的书还在路上。。。。还要深入学习啊。
a3212b12 2016-12-01
  • 打赏
  • 举报
回复
引用 2 楼 a3212b12 的回复:
规定合同一定要连号,这是不非常合理的。假如A 今天做了一个合同05,明天做个06,后天发现05号不对,需要删除,这时,难道你要去补这个05?
规定合同一定要连号,这是不非常合理的 手工时代,规定下连号,有好处。 都用上程序了,还要规定连号,有什么用处?
a3212b12 2016-12-01
  • 打赏
  • 举报
回复
规定合同一定要连号,这是非常合理的。假如A 今天做了一个合同05,明天做个06,后天发现05号不对,需要删除,这时,难道你要去补这个05?
jthkl 2016-11-23
  • 打赏
  • 举报
回复
网上查帖子,觉得是不是要使用数据库锁? 先新建一行数据,然后锁定表格,使得其他用户不能insert,这个时候select count一下,然后update一下合同编号字段,然后解锁,其他用户可以继续新建数据?不知思路对不对。 但是以前重来没用过数据库锁,不知道怎么在代码中实现?

16,554

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧