一下是一个订单插入的存储过程,但在执行时有时候提示出错,经过在ASP.NET中跟踪后发现即使是相同的数据有时候存储过程的执行会成功,有时候又失败,特别是在存储过程中加入事务处理后,出错的概率更高,去掉事务处理后出错的概率就比较低了,实在是搞不懂,请大家指教,谢谢!
ALTER PROCEDURE [dbo].[usp_AddOrderBill]
@OrderBillCode varchar(50),
@CustomerId int,
@OperatorEmployeeId int,
@SellerEmployeeId int,
@PayTypeId int,
@OrderBillTypeId int,
@StoreHouseId int,
@OrderDate datetime,
@TotalMoney decimal(18,4),
@IsPayed bit,
@PayedDate datetime,
@IsAllShipedOut bit,
@Res varchar(50),
@Visible bit
AS
BEGIN
declare @billCode varchar(50)
declare @todayCode varchar(50) select @todayCode= convert(varchar(8),getdate(),112)
set @todayCode=right(@todayCode,6)
--begin transaction T
select top 1 @billCode=OrderBillCode from tb_OrderBill order by OrderBillId desc
if (@billCode is null)
begin
set @OrderBillCode='XS'+@todayCode+'001'
end
else
begin
if(@todayCode<>substring(@billCode,3,6))
begin
set @OrderBillCode='XS'+@todayCode+'001'
end
else
begin
declare @code int
set @code=Convert(int,substring(@billCode,9,3))
set @code=@code+1
set @OrderBillCode='00'+convert(varchar(50),@code)
set @OrderBillCode=right(@OrderBillCode,3)
set @OrderBillCode='XS'+@todayCode+@OrderBillCode
end
end
--以上代码获取订单编号,订单编号是自动生成的,形式是"XS"+今日日期+顺序号,比如:“XS090729001”"XS090729002" 等
INSERT INTO [dbo].[tb_OrderBill](
OrderBillCode,
CustomerId,
OperatorEmployeeId,
SellerEmployeeId,
PayTypeId,
OrderBillTypeId,
StoreHouseId,
OrderDate,
TotalMoney,
IsPayed,
PayedDate,
IsAllShipedOut,
Res,
Visible
) VALUES (
@OrderBillCode,
@CustomerId,
@OperatorEmployeeId,
@SellerEmployeeId,
@PayTypeId,
@OrderBillTypeId,
@StoreHouseId,
@OrderDate,
@TotalMoney,
@IsPayed,
@PayedDate,
@IsAllShipedOut,
@Res,
@Visible)
--if(@@error<>0)
--begin
-- rollback transaction T
-- return 0
--end
--else
-- begin
--commit transaction T
return SCOPE_IDENTITY()
--end
END
ALTER PROCEDURE [dbo].[usp_AddOrderBill]
@OrderBillCode varchar(50),
@CustomerId int,
@OperatorEmployeeId int,
@SellerEmployeeId int,
@PayTypeId int,
@OrderBillTypeId int,
@StoreHouseId int,
@OrderDate datetime,
@TotalMoney decimal(18,4),
@IsPayed bit,
@PayedDate datetime,
@IsAllShipedOut bit,
@Res varchar(50),
@Visible bit
AS
BEGIN
declare @billCode varchar(50)
declare @todayCode varchar(50) select @todayCode= convert(varchar(8),getdate(),112)
set @todayCode=right(@todayCode,6)
--begin transaction T
select top 1 @billCode=OrderBillCode from tb_OrderBill order by OrderBillId desc
if (@billCode is null)
begin
set @OrderBillCode='XS'+@todayCode+'001'
end
else
begin
if(@todayCode<>substring(@billCode,3,6))
begin
set @OrderBillCode='XS'+@todayCode+'001'
end
else
begin
declare @code int
set @code=Convert(int,substring(@billCode,9,3))
set @code=@code+1
set @OrderBillCode='00'+convert(varchar(50),@code)
set @OrderBillCode=right(@OrderBillCode,3)
set @OrderBillCode='XS'+@todayCode+@OrderBillCode
end
end
--以上代码获取订单编号,订单编号是自动生成的,形式是"XS"+今日日期+顺序号,比如:“XS090729001”"XS090729002" 等
INSERT INTO [dbo].[tb_OrderBill](
OrderBillCode,
CustomerId,
OperatorEmployeeId,
SellerEmployeeId,
PayTypeId,
OrderBillTypeId,
StoreHouseId,
OrderDate,
TotalMoney,
IsPayed,
PayedDate,
IsAllShipedOut,
Res,
Visible
) VALUES (
@OrderBillCode,
@CustomerId,
@OperatorEmployeeId,
@SellerEmployeeId,
@PayTypeId,
@OrderBillTypeId,
@StoreHouseId,
@OrderDate,
@TotalMoney,
@IsPayed,
@PayedDate,
@IsAllShipedOut,
@Res,
@Visible)
--if(@@error<>0)
--begin
-- rollback transaction T
-- return 0
--end
--else
-- begin
--commit transaction T
return SCOPE_IDENTITY()
--end
END
BEGIN
set nocount on
declare @billCode varchar(50)
declare @todayCode varchar(50)
另外你的单据编号,可以参考一下这个:--关于ERP公司单据编码的问题。
一般ERP企业里,要用到很多种类的单据,是有一定得编码规则的,如销售订单编码:Seord123,前面的字符为单据编号前缀,
后面的数字为这类单据的流水号,依次加1,那他们是怎么实现这种单据编号的。
他们一般是把各类单据的编号统一放在一个表里,其中字段有单据TYPE(单据类型),PREC(单据前缀),NO(当前的数字编号)等。
步骤是这样的:
--1、从这个表里取前缀和数字部分+1组合起来作为单据号。
--2、将单据保存到业务表之前,先判断业务表里是否已存在这个单据编号,没有的话,就插入数据,然后更新单据编号表中的NO=NO+1
--4、如果有的话,将该单据号的数字再加1,然后再进行插入判断,反复进行,直到插入数据为止,当然别忘了更新单据编号表中的NO为最新值。
--建议,你在可能出错的地,print 'dddddd' 一下!
--应该是数据值的,错误!
1,把insert into 的语句,写成,字符串的!
2,通过exec (@sql) 来执行!(在执行之前,先print(@sql)看他的正确性!)
取单据号这块,要再优化一下。
另外,单据一般是一个主表,一个从表。tb_OrderBill是主表吧?从表呢?
获得订单号这块,我帮你优化一下。
求订单号一段直接Select下L
select 'xs'+@todaycode+right('00'+isnull(max(right(OrderBillCode,3)),0)+1,3) as billcode
你在取得下一个单据号的时候,别人也可能同时取得这个单据号,他先保存了,你的没保存。
你在插入单据时,单据号就会有冲突。
你在插入单据编号前,先判断你这个单据号,是否存在,不存在的时候插入,已经存在的话就重新取号。
然后继续判断,直至插入数据。
这样的话,就不会有问题的。
国内一些大ERP厂商就这么做的,我以前做过。
(散人) :对应的订单明细表会有多条记录,我不知道怎么把多条记录的信息一次新传入到存储过程中。呵呵。所以我就把它独立到存储过程的外面利用ADO.NET来完成了,还请指教
存储过程的完整代码如下:
ALTER PROCEDURE [dbo].[usp_AddOrderBill]
@OrderBillCode varchar(50),
@CustomerId int,
@OperatorEmployeeId int,
@SellerEmployeeId int,
@PayTypeId int,
@OrderBillTypeId int,
@StoreHouseId int,
@OrderDate datetime,
@TotalMoney decimal(18,4),
@IsPayed bit,
@PayedDate datetime,
@IsAllShipedOut bit,
@Res varchar(50),
@Visible bit
AS
BEGIN
--set nocount on
declare @billCode varchar(50)
declare @todayCode varchar(50) select @todayCode= convert(varchar(8),getdate(),112)
set @todayCode=right(@todayCode,6)
begin transaction T
select top 1 @billCode=OrderBillCode from tb_OrderBill order by OrderBillId desc
if (@billCode is null)
begin
set @OrderBillCode='XS'+@todayCode+'001'
end
else
begin
if(@todayCode<>substring(@billCode,3,6))
begin
set @OrderBillCode='XS'+@todayCode+'001'
end
else
begin
declare @code int
set @code=Convert(int,substring(@billCode,9,3))
set @code=@code+1
set @OrderBillCode='00'+convert(varchar(50),@code)
set @OrderBillCode=right(@OrderBillCode,3)
set @OrderBillCode='XS'+@todayCode+@OrderBillCode
end
end
INSERT INTO [dbo].[tb_OrderBill](
OrderBillCode,
CustomerId,
OperatorEmployeeId,
SellerEmployeeId,
PayTypeId,
OrderBillTypeId,
StoreHouseId,
OrderDate,
TotalMoney,
IsPayed,
PayedDate,
IsAllShipedOut,
Res,
Visible
) VALUES (
@OrderBillCode,
@CustomerId,
@OperatorEmployeeId,
@SellerEmployeeId,
@PayTypeId,
@OrderBillTypeId,
@StoreHouseId,
@OrderDate,
@TotalMoney,
@IsPayed,
@PayedDate,
@IsAllShipedOut,
@Res,
@Visible)
if(@@error<>0)
begin
rollback transaction T
return 0
end
else
begin
commit transaction T
return SCOPE_IDENTITY()
end
END
SET releaseTime = DATEADD(month, 1, releaseTime)
WHERE (DATEDIFF(month, releaseTime, GETDATE()) = 1) AND (productId < 100)
这个代码尽然可以运行了!这里我通过限定productId来保证只有一条记录需要修改,竟然就成功了!真是奇怪啊,如果有两条记录需要修改则提示“子查询返回值不止一个”的错误!
如果有2个人几乎同时保存的话,就会出问题了,因为你的那个订单号码可能已经被别人占用了,所以你取得订单号码的时间要尽量短,保存的时候要判断你的那个订单号码是否在单据里已经存在了,如果存在的话,你要再取一个,就这么简单的道理。看看我在17楼写的,非常明白了。
BYE
set @code=Convert(int,substring(@billCode,9,3))
set @code=@code+1
set @OrderBillCode='00'+convert(varchar(50),@code)
set @OrderBillCode=right(@OrderBillCode,3)
set @OrderBillCode='XS'+@todayCode+@OrderBillCode 这段代码有问题,当今天的单据超过9时,在录入新的单据,单据号会超过定义的单据号长度
改成
set @code=Convert(int,right(@billCode,3))
set @OrderBillCode=right(@OrderBillCode,3)
看看这个表:tb_OrderBill触发器的情况。
不要把update的操作和后面插新单的操作放在一个事务中, 这样造成的对单号保存表的占用时间极短,就算后面的单号插入操作不成功,唯一造成的问题就是造成单号断号,并不影响实际使用。
EXEC @return_value = [dbo].[usp_AddOrderBill]
@OrderBillCode = N'XS090730017',
@CustomerId = 657,
@OperatorEmployeeId = 47,
@SellerEmployeeId = 46,
@PayTypeId = 1,
@OrderBillTypeId = 1,
@StoreHouseId = 4,
@OrderDate = N'2009-7-30 0:00:00',
@TotalMoney = 6564,
@IsPayed = false,
@PayedDate = N'1900-1-1 0:00:00',
@IsAllShipedOut = true,
@Res = N' ',
@Visible = trueSELECT 'Return Value' = @return_valueGO消息 547,级别 16,状态 0,过程 usp_AddOrderBill,第 51 行
INSERT 语句与 FOREIGN KEY 约束"FK_tb_OrderBill_tb_Customer"冲突。该冲突发生于数据库"MISServer2",表"dbo.tb_Customer", column 'CustomerId'。
语句已终止。