关于多用户操作的问题

fstao 2007-07-10 09:19:07
存储过程如下:
ALTER PROCEDURE p_bs_product_save
@id int= Null Output
@code varchar (300) ,
@billcode varchar (300)

as
begin

insert t_wh_billofdocument([code],[billcode],[bs_customer_id])
values (@code,@billcode)

set @id = @@Identity
end



当很多用户同时执行同一条存储过程(p_bs_product_save)时,比如有两个用户分别是A和B,当A和B执行这一条存储过程时,本来A应返回的 @id=801,B应返回的@id=802的,但当网络、人员操作等等原因时,而且又是同时执行同一条存储过程时,变成A返回的@id=802,而B返回的@id=801,就是A用户取走了B用户的@id的值,而B用户取走了A用户的@id的值;如果要避免这个问题,是不是一定要加上事务才行?把上面的代码改一下:

ALTER PROCEDURE p_bs_product_save
@id int= Null Output
@code varchar (300) ,
@billcode varchar (300)

as
begin

declare @iError int

BEGIN TRANSACTION inserttran aaa
insert t_wh_billofdocument([code],[billcode],[bs_customer_id])
values (@code,@billcode)

set @id = @@Identity

set @iError = @@error
if @iError=0
commite tran aaa
else
rollback tran aaa

end



这样做会不会避免A用户与B用户相互取@id的问题,就是多用户取@id的问题?这样做会不会一个一个用户执行同一个存储过程时,一个一个来取@id值?
...全文
231 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
hellowork 2007-07-11
  • 打赏
  • 举报
回复

set @id = @@Identity
改成:
set @id = scope_identity()
就绝对不会出现这个问题,而且可以不用事务.
还有,楼主的错误捕捉时机不对,若要保存@@error值,必须在INSERT之后的第一行保存或判断该值,因为@error反映的时最近一次执行的语句的状况,而无论这个语句是否是SQL.所以,楼主写的实际是set @id = @@Identity这个语句是否成功执行,而不是INSERT是否成功执行.
这样改一下:
ALTER PROCEDURE p_bs_product_save
@id int= Null Output
@code varchar (300) ,
@billcode varchar (300)
as
declare @iError int
BEGIN TRANSACTION aaa
insert t_wh_billofdocument([code],[billcode],[bs_customer_id])
values (@code,@billcode)
set @iError = @@error /*保存错误号*/
set @id = scope_identity() /*获取标识值*/
if @iError=0
commite tran aaa
else
rollback tran aaa
GO

或者:
ALTER PROCEDURE p_bs_product_save
@id int= Null Output
@code varchar (300) ,
@billcode varchar (300)
as
insert t_wh_billofdocument([code],[billcode],[bs_customer_id])
values (@code,@billcode)
if @@error <> 0
return /*如果发生错误则结束存储过程*/
else
set @id = scope_identity() /*获取标识值*/
GO
fstao 2007-07-11
  • 打赏
  • 举报
回复
其实我知道标识值是由SQLSERVER系统自身控制的,不存在并发问题,也就是说不会重复,我的意思是下面的存储过程:
ALTER PROCEDURE p_bs_product_save
@id int= Null Output
@code varchar (300) ,
@billcode varchar (300)

as
begin

declare @iError int

BEGIN TRANSACTION inserttran aaa
insert t_wh_billofdocument([code],[billcode],[bs_customer_id])
values (@code,@billcode)

set @id = @@Identity

set @iError = @@error
if @iError=0
commite tran aaa
else
rollback tran aaa

end

如果多用户同时执行这一条存储过程时(p_bs_product_save),比如有用户A和B同时执行,正常来说A用户取出的@id=801,而B用户取出的@id=802,我在这个存储过程里没有加事务之前时,当很多用户同时操作时,有时A用户取@id=802(取走了B用户的),而B用户取@id=801(取走了A用户的),我不希望出现这种情况,如果加上事务会不会解决这种情况呢?或者“hellowork(一两清风) ”那样把
set @id = @@Identity
改成:
set @id = scope_identity()
也会不会解决这种情况呢?
hellowork 2007-07-10
  • 打赏
  • 举报
回复
如果用事务的话,还是用set @id = @@Identity,能否解决多用户并发的问题?
---------------------------------------------------------------------------------
标识值是由SQLSERVER系统自身控制的,不存在并发问题,也就是说不会重复,也与事务无关,最关键的是怎样提取该标识值.但是事务失败时,标识值会报废,新标识值将在报废标识值的基础上自增.
hellowork 2007-07-10
  • 打赏
  • 举报
回复
如果插入数据的表中没有触发器或触发器中不会向含有IDENTITY列的表中插入数据,那么在INSERT后使用@@identity获得的值与scope_identity获得的值是完全相同的,无论怎么并发也不会取到其他用户插入生成的标识值,因为@@identity是指该连接(或用户)的最近一次插入生成的标识值,与其它连接(其他用户)生成的标识值毫无关系,它的"全局"不是真正意义上的针对所有连接(用户)的全局,而只是针对该连接的,各个连接(用户)之间的@@identity值互不干扰,老死不相往来.
fstao 2007-07-10
  • 打赏
  • 举报
回复
如果用事务的话,还是用set @id = @@Identity,能否解决多用户并发的问题?
fstao 2007-07-10
  • 打赏
  • 举报
回复
如果用事务的话,还是用set @id = @@Identity,能否达到多用户并发的问题?
hellowork 2007-07-10
  • 打赏
  • 举报
回复
不用事务,只要把@@identity换成scope_identity()了,原因是在存储过程中使用INSERT插入记录时,scope_identity()返回的就是该INSERT产生的ID,绝对不会是其他用户INSERT产生的ID,可以说scope_identity()就是为存储过程中INSERT操作量身定做的.
@@identity则是全局的,尤其当INSERT的表中有INSERT触发器,而且触发器向另一个有IDENTITY标识列的表插入数据时,@@identity返回的将是那个表的最大标识,而不是该表的最大标识.
具体请楼主查看一下@@identity和scope_identity()帮助.

ALTER PROCEDURE p_bs_product_save
@id int= Null Output
@code varchar (300) ,
@billcode varchar (300)
as
begin
insert t_wh_billofdocument([code],[billcode],[bs_customer_id])
values (@code,@billcode)
set @id = scope_identity() /*修改这句*/
end
GO
fstao 2007-07-10
  • 打赏
  • 举报
回复
为什么把

set @id = @@Identity
改成:
set @id = scope_identity()
hellowork 2007-07-10
  • 打赏
  • 举报
回复

set @id = @@Identity
改成:
set @id = scope_identity()

34,590

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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