delphi数据库并发问题----如何保证采购流水号是唯一的

ansameye168 2008-02-21 05:25:18
delphi数据库并发问题----如何保证采购流水号是唯一的


表名:po_table

sql自动编号 总流水号 日流水号  物料名 数量 录入者
autono allno pono marno qty loginuser
1 001 po200801001 C 8 翠花
2 001 po200801001 R 9 翠花
3 001 po200801001 L 100 翠花
4 001 po200801001 PCB 12 刘明

5 002 po200801002 BOX 19 刘飞

问题:
现在总流水号和日流水号均会自动取得并+1,如果同时有100个人在录入采购单,且有10人同时按下保存,怎么样才能保证在
翠花在录入以上记录时,会自动锁定日流水号(po200801001)

sql自动编号 总流水号 日流水号  物料名 数量 录入者
3 001 po200801001 L 100 翠花

刘明在录入保存时,出现的单号是po200801002:

sql自动编号 总流水号 日流水号  物料名 数量 录入者
autono allno pono marno qty loginuser
4 002 po200801002 PCB 12 刘明
而不是像上面数据库的号是po200801001:
sql自动编号 总流水号 日流水号  物料名 数量 录入者
autono allno pono marno qty loginuser
4 001 po200801001 PCB 12 刘明

说的简单就是当A在输入数据保存时,会自动锁定allno,pono,当第二个人B输入要保存时,会自动在A锁定的单号加1
如A要保存的单号是PO001,当A保存时B又要取单号,因为A进行了锁定,所以B取的单号为PO002,C要取号而B也进行了锁定
C取的号是PO003

不知道那位大侠有好的办法,还是我的表本身设计就有问题,请尽量回复详细一点,谢谢!


--建表:
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[po_table]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[po_table]
GO

CREATE TABLE [dbo].[po_table] (
[autono] [int] IDENTITY (1, 1) NOT NULL ,
[allno] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
[pono] [char] (20) COLLATE Chinese_PRC_CI_AS NULL ,
[marno] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
[qty] [int] NULL ,
[loginuser] [char] (10) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO


--插入数据
insert po_table select '001','po200801001','c','8','翠花'
insert po_table select '001','po200801001','r','9','翠花'
insert po_table select '001','po200801001','l','100','翠花'
insert po_table select '001','po200801001','pcb','12','刘明'
insert po_table select '002','po200801002','box','19','刘飞'

select * from po_table
...全文
471 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
labway 2008-02-28
  • 打赏
  • 举报
回复
你这个和我生成条码系统的例子差不多,没有看楼上的各位怎么做,我做的方法是有一个表专门存储最大号,然后每次生成新的条码时,通过存储过程,来获取最大号加1,同时将最大的条码号更新成目前的号码,没有出过错误
ansameye168 2008-02-27
  • 打赏
  • 举报
回复
再等二天看有没有那位大哥发队列的例子来看一下,没的话就结帖,谢谢大家!
dll0629 2008-02-26
  • 打赏
  • 举报
回复
如果前3条一张单据,那一起存,不要一条一条存
如果是单号重复的,在存数据前,那循环判断单号在数据库是否存在,存在+1继续循环,不存在,接下去操作,操作完了提示单号,最好用个事务,不用也没什么关系,基本上不会重复
ansameye168 2008-02-26
  • 打赏
  • 举报
回复
上面的错了,麻烦各位老大发点sql队列的例子上来看一下!
ansameye168 2008-02-25
  • 打赏
  • 举报
回复
谢谢大家,我再试试sql队列,因为没用个这个东东,所以不会用,要是队列问题解决的话,所有问题都解决了,谢谢!
ansameye168 2008-02-25
  • 打赏
  • 举报
回复
感谢AHLKJ,经测试你的代码和思想是正确的,只是建库脚本应该改为:

CREATE TABLE [dbo].[BillNo](
[Id] [int] IDENTITY(1,1) NOT NULL,
[BillName] [varchar](20) COLLATE Chinese_PRC_CI_AS NOT NULL,
[MaxNo] [int] NULL,
[MaxDate] [varchar](20) COLLATE Chinese_PRC_CI_AS NULL,
[Prefix] [varchar](20) COLLATE Chinese_PRC_CI_AS NULL,
[NumBit] [int] NULL CONSTRAINT [DF_BillNo_NumBit] DEFAULT ((0)),
[Style] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
[Memo] [text] COLLATE Chinese_PRC_CI_AS NULL,
[CreateDate] [datetime] NULL CONSTRAINT [DF_BillNo_CreateDate] DEFAULT (getdate()),
[EditDate] [datetime] NULL,
[State] [int] NULL CONSTRAINT [DF_BillNo_State] DEFAULT ((0)),
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]


GO
ansameye168 2008-02-25
  • 打赏
  • 举报
回复
各位大哥,在baidu找了半天找不到事务处理的例子,能不能麻烦各位老大发点例子上来看一下!
xiaxia421 2008-02-25
  • 打赏
  • 举报
回复
设置流水号为主键,然后建一个存储过程计算流水号,最后保存就OK!记得用事务处理!
cloudlyanhart 2008-02-25
  • 打赏
  • 举报
回复
设置流水号为主键。。。
oushengfen 2008-02-25
  • 打赏
  • 举报
回复
锁,不错的.
lqwxfdwj 2008-02-23
  • 打赏
  • 举报
回复
别外创建一个表用来存储单号是比较好的选择;
AHLKJ 2008-02-23
  • 打赏
  • 举报
回复
使用专用的表来存放最大编号,使用存储过程来获取编号。


CREATE TABLE [dbo].[BillNo](
[Id] [int] IDENTITY(1,1) NOT NULL,
[BillName] [varchar](20) COLLATE Chinese_PRC_CI_AS NOT NULL,
[MaxNo] [int] NULL,
[MaxDate] [varchar](20) COLLATE Chinese_PRC_CI_AS NULL,
[Prefix] [varchar](20) COLLATE Chinese_PRC_CI_AS NULL,
[NumBit] [int] NULL CONSTRAINT [DF_BillNo_NumBit] DEFAULT ((0)),
[Style] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
[Memo] [text] COLLATE Chinese_PRC_CI_AS NULL,
[CreateDate] [datetime] NULL CONSTRAINT [DF_BillNo_CreateDate] DEFAULT (getdate()),
[EditDate] [datetime] NULL,
[State] [int] NULL CONSTRAINT [DF_BillNo_State] DEFAULT ((0)),
CONSTRAINT [PK_BillNo] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

CREATE PROCEDURE [dbo].[p_GetBillNo] --产生按年月日排列的档案号
@BillName varchar(20),
@No varchar(20) output, --为产生的档案号
@NumBit int = 4 --编号位数

AS
DECLARE @MaxNo int,
@MaxDate varchar(20),
@Prefix varchar(20),
@xNumBit int,
@CurrDate varchar(12),
@FILL_ZERO int,
@iMaxNo int

SET @FILL_ZERO = 100000000
SET @CurrDate = CONVERT(VARCHAR(8), GETDATE(),112)

SELECT @MaxNo = MaxNo, @MaxDate = MaxDate, @Prefix = Prefix, @xNumBit = NumBit FROM BillNo WITH(XLOCK) WHERE BillName = @BillName
IF @@ROWCOUNT <> 1 RETURN -1

IF @xNumBit <> 0 SET @NumBit = @xNumBit

IF @MaxDate <> @CurrDate OR @MaxDate IS NULL OR @MaxNo IS NULL
SET @iMaxNo = 1
ELSE
SET @iMaxNo = @MaxNo + 1

UPDATE BillNo
SET MaxNo = @iMaxNo, MaxDate = @CurrDate, EditDate = GetDate() WHERE BillName = @BillName
IF @@ROWCOUNT <> 1 RETURN -1

SET @No = COALESCE(@Prefix, '') + @CurrDate + RIGHT(CAST(@FILL_ZERO + @iMaxNo AS VARCHAR), @NumBit)

RETURN 1
liangpei2008 2008-02-22
  • 打赏
  • 举报
回复
nhconch 说得没错
1.用Delphi算法实现
2.用SQL中的UDF绑定到某字段上做默认值
ansameye168 2008-02-22
  • 打赏
  • 举报
回复
学习中,测试中,忘了和大家说一下,autono是关键字是sql自动生成,会自动加1,总流水号和日流水号由函数自动生成
sql自动编号 总流水号 日流水号  
autono allno pono
看来sql里的学问可大了,得好好的向各位学习学习!
阿三 2008-02-22
  • 打赏
  • 举报
回复
首选要利用事务来进行控制数据的完整性.
第二,你用的数据库为sqlserver,可以在进行保存时,先执行一个 update po_table set allno=allno where autono=1 这样的语句先把表锁住,这样其它的用户在进行保存时,就会等待前一个事务提交或回滚后才进行操作.
jadeluo 2008-02-22
  • 打赏
  • 举报
回复
另外建立一个数据表, 里面保存着某序列编号目前已分配到的最大值。在进行新增记录的操作之前,用Select语句读出该值,然后用Update语句递增该值。
nhconch 2008-02-22
  • 打赏
  • 举报
回复
一般是在保存时才生成流水号,为保证号码唯一有常用的两种方法:
1、程序生成,保存时开事务,算号、写号、保存、结束事务。
2、由数据库生成,在数据库中编写专门的函数取于算号,将字段默认值设为调用该函数生成号码。
lyguo 2008-02-22
  • 打赏
  • 举报
回复
专门再建一个表,用一个字段来存储这个流水号,每次先把这个流水号加1.
ansameye168 2008-02-22
  • 打赏
  • 举报
回复
确实是这样的问题,但是怎样才能做到,在sql里锁的操作基本上是一无所知。
ansameye168 2008-02-22
  • 打赏
  • 举报
回复
思想是知道了
无耐对sql不精,不知位大侠能发点例子上来看看,谢谢!
加载更多回复(1)

2,497

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 数据库相关
社区管理员
  • 数据库相关社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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