如何将唯一值插入非身份字段
我正在尝试插入一个已建立的表,该表具有主键字段和另一个唯一的字段(称为 field1)(这个另一个唯一字段具有阻止我插入的唯一约束)。 Field1 不是标识字段,因此它不会自动编号。不幸的是我不能改变桌子。现有的插入是使用代码来递增的,并且都涉及循环/游标。像 SELECT MAX(field1) + 1 这样的东西
那么,有没有办法在不循环/游标的情况下执行此插入?这个字段对我来说毫无意义,但已经有超过 500,000 条记录使用他们愚蠢的编号方案,所以我必须尊重这一点。
这是简化的(ReceiptNumber 是我想要插入唯一的字段),但是:
SET XACT_ABORT ON
Begin Transaction TransMain
Declare @nvErrMsg nvarchar(4000)
--Insert inventory receipts
Insert Into Avanti_InventoryReceipts (
ReceiptNumber , ItemNumber , ReceiptDate , OrderNumber , JobNumber , Supplier ,
LineNumber , MultiLineNumber , [Status] , QtyOrdered , QtyReceived , QtyToReceive ,
QtyBackOrdered , Cost , Wholesale , LastCost , QtyToInvoice , QtyUsed ,
ReferenceNumber , [Description] , SupplierType , Processed , DateExpected , DateReceived ,
AccountNumber , Reference2 , EmployeeCode , ExtraCode , Location , RollNumber ,
QtyIssues , Notes , NumPackages , BundleSize , ConsignmentUnitPrice , RecFromProduction ,
QtyCommitted )
SELECT ( SELECT MAX(ReceiptNumber) + 1 FROM Avanti_inventoryReceipts ) , CR.ItemNumber , Convert(char(8), GETDATE(), 112) , PONum , 'FL-INV' , PH.POVendor ,
0 , 0 , 'O' , CR.QtyOrdered , QtyReceivedToday , QtyReceivedToday ,
Case @closePO
When 'N' Then Case When ( QtyOrdered - QtyReceivedToday ) < 0 Then 0 Else ( QtyOrdered - QtyReceivedToday) End
When 'Y' Then 0
Else 0 End
, PD.TransCost * QtyReceivedToday , IH.PriceWholeSale , IH.CostLast , QtyReceivedToday , 0 ,
'' , PODetailDescription , '' , '' , '' , Convert(char(8), GETDATE(), 112) ,
'' , '' , @employeeCode , '' , 'F L E X O' , '' ,
0 , 'Flexo Materials' , 0 , 0 , 0 , '' , 0
FROM FI_CurrentReceiptData CR
LEFT JOIN Avanti_PODetails PD ON CR.PONum = PD.PONumber
LEFT JOIN Avanti_POHeader PH ON CR.PONum = PH.PONumber
LEFT JOIN Avanti_InventoryHeader IH ON CR.ItemNumber = IH.ItemNumber
IF @@ERROR <> 0
Begin
Select @nvErrMsg = 'Error entering into [InventoryReceipts] -' + [description]
From master..sysmessages
Where [error] = @@ERROR
RAISERROR ( @nvErrMsg , 16, 1 )
Goto Err_
End
Commit Transaction TransMain
Goto Exit_
Err_:
Rollback Transaction TransMain
Exit_:
SET XACT_ABORT OFF
I'm trying to do an insert into an established table which has a primary key fields and another field (call it field1) that is unique (this other unique field has a unique constraint preventing my inserts). Field1 is not an identity field, so it does NOT autonumber. Unfortunately I can't change the table. Existing inserts are made using code to increment and all involve looping/cursors. Something like SELECT MAX(field1) + 1
So, is there anyway to do this insert without looping/cursor? This field means nothing to me, but there are already 500,000+ records using their silly numbering scheme, so I must respect that.
This is simplified (ReceiptNumber is the field I want to insert unique), but:
SET XACT_ABORT ON
Begin Transaction TransMain
Declare @nvErrMsg nvarchar(4000)
--Insert inventory receipts
Insert Into Avanti_InventoryReceipts (
ReceiptNumber , ItemNumber , ReceiptDate , OrderNumber , JobNumber , Supplier ,
LineNumber , MultiLineNumber , [Status] , QtyOrdered , QtyReceived , QtyToReceive ,
QtyBackOrdered , Cost , Wholesale , LastCost , QtyToInvoice , QtyUsed ,
ReferenceNumber , [Description] , SupplierType , Processed , DateExpected , DateReceived ,
AccountNumber , Reference2 , EmployeeCode , ExtraCode , Location , RollNumber ,
QtyIssues , Notes , NumPackages , BundleSize , ConsignmentUnitPrice , RecFromProduction ,
QtyCommitted )
SELECT ( SELECT MAX(ReceiptNumber) + 1 FROM Avanti_inventoryReceipts ) , CR.ItemNumber , Convert(char(8), GETDATE(), 112) , PONum , 'FL-INV' , PH.POVendor ,
0 , 0 , 'O' , CR.QtyOrdered , QtyReceivedToday , QtyReceivedToday ,
Case @closePO
When 'N' Then Case When ( QtyOrdered - QtyReceivedToday ) < 0 Then 0 Else ( QtyOrdered - QtyReceivedToday) End
When 'Y' Then 0
Else 0 End
, PD.TransCost * QtyReceivedToday , IH.PriceWholeSale , IH.CostLast , QtyReceivedToday , 0 ,
'' , PODetailDescription , '' , '' , '' , Convert(char(8), GETDATE(), 112) ,
'' , '' , @employeeCode , '' , 'F L E X O' , '' ,
0 , 'Flexo Materials' , 0 , 0 , 0 , '' , 0
FROM FI_CurrentReceiptData CR
LEFT JOIN Avanti_PODetails PD ON CR.PONum = PD.PONumber
LEFT JOIN Avanti_POHeader PH ON CR.PONum = PH.PONumber
LEFT JOIN Avanti_InventoryHeader IH ON CR.ItemNumber = IH.ItemNumber
IF @@ERROR <> 0
Begin
Select @nvErrMsg = 'Error entering into [InventoryReceipts] -' + [description]
From master..sysmessages
Where [error] = @@ERROR
RAISERROR ( @nvErrMsg , 16, 1 )
Goto Err_
End
Commit Transaction TransMain
Goto Exit_
Err_:
Rollback Transaction TransMain
Exit_:
SET XACT_ABORT OFF
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你可以这样做:
You could do this:
为什么不循环?应该是相当有效率的。
由于您已经对该字段设置了 UNIQUE 约束,因此您可以:
MAX(field1) + 1
。由于UNIQUE字段上有索引,所以MAX
速度很快。大多数时候,INSERT 会立即成功。在极少数情况下,并发用户尝试插入相同的值,您可以通过尝试“下一个”值来妥善处理。
Why not looping? It should be quite efficient.
Since you already have a UNIQUE constraint on the field, you can:
MAX(field1) + 1
. Since there is index on UNIQUE field,MAX
is fast.Most of the time, the INSERT will succeed right away. In rare instances where a concurrent user tries to insert the same value, you'll handle that gracefully by trying the "next" value.
我在客户端代码中添加了一个从 0 开始的自动编号并将其传入。现在我将该值添加到最大收据编号中以获得唯一的编号。另外,我意识到我已经在 FI_CurrentReceiptData 中有一个身份列,但我不想使用该列,因为它不会为每个收据集从 0 开始,并且每次重新播种身份似乎都是浪费处理器时间。
I added an autonumber starting from 0 in client code and passed that in. Now I'm adding that value to the max receiptnumber to get a unique one. Also, I realized I already had an identity column in FI_CurrentReceiptData, but I didn't want to use that one because it won't start at 0 for each receipt set, and reseeding the identity each time seems like a waste of processor time.