如何在非标识字段中插入唯一值

时间:2011-09-01 21:02:47

标签: sql sql-server database sql-server-2000

我正在尝试插入已建立的表,该表具有主键字段和另一个唯一的字段(称为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

3 个答案:

答案 0 :(得分:0)

你可以这样做:

insert into mytable (field1, field2, ...)
values (( SELECT MAX(field1) + 1 from mytable), 'value2', ...);

答案 1 :(得分:0)

为什么不循环?它应该非常有效。

由于您已在该字段上拥有UNIQUE约束,您可以:

  • 只需尝试插入MAX(field1) + 1即可。由于UNIQUE字段上有索引,MAX很快。
  • 如果它通过,那么你就完成了。
  • 如果失败(通常会在客户端代码中显示为异常),请再试一次,直到成功为止。

大多数情况下,INSERT会立即成功。在并发用户尝试插入相同值的极少数情况下,您可以通过尝试“下一个”值来优雅地处理它。

答案 2 :(得分:0)

我在客户端代码中添加了一个从0开始的自动编号并将其传入。现在我将该值添加到最大收据数以获得唯一的值。此外,我意识到我已经在FI_CurrentReceiptData中有一个标识列,但我不想使用它,因为它不会从每个收据集的0开始,并且每次重新播种标识似乎浪费了处理器时间。