【问题标题】:How to Auto-Increment Non-Primary Key? - SQL Server如何自动增加非主键? - SQL 服务器
【发布时间】:2011-02-05 18:27:11
【问题描述】:
CREATE TABLE SupplierQuote
(
supplierQuoteID int identity (3504,2) CONSTRAINT supquoteid_pk PRIMARY KEY,
PONumber int identity (9553,20) NOT NULL
.
.
.
CONSTRAINT ponumber_uq UNIQUE(PONumber)
);

上面的ddl产生错误:

消息 2744,第 16 级,状态 2,第 1 行 指定了多个标识列 对于表“供应商报价”。只有一个 允许每个表的标识列。

我该如何解决?我希望 PONumber 自动递增。

【问题讨论】:

    标签: sql sql-server database tsql normalization


    【解决方案1】:

    您无法解决您的问题 - 每个表只能有一个 IDENTITY 列。没办法,抱歉。

    唯一的“hackish”解决方案是拥有一个单独的表,只需要一个 INT IDENTITY 字段,并在插入时从该帮助表中获取最新值到您的实体中(例如,使用触发器)。不是很漂亮,但它可能适合你。

    【讨论】:

      【解决方案2】:

      每个表不能有多个标识列。我认为您最好的选择是将 PO 数据提取到单独的表中,然后将两者与 FK 列相关联。

      SupplierQuote
      -------------
      supplierQuoteID (PK/identity)
      purchaseOrderID (FK to PurchaseOrder.purchaseOrderID)
      otherColumn1
      
      PurchaseOrder
      -------------
      purchaseOrderID (PK/identity)
      otherColumn1
      

      【讨论】:

      • 问题是当supplierQuoteID记录被删除时,父表中的purchaseOrder就没有用了。因此,我将不得不编写一个触发器来擦除父 purchaseOrder 记录。我决定使用随机生成器从前端手动插入 PONumber。
      • 如果您想确保 PONumber 是唯一的,我不会使用随机数生成器。我会使用 Guid.NewGuid()。保证数据库唯一性的两种最简单的方法是使用标识或 GUID。
      • 您也可以级联删除 - 当您删除供应商报价时,您将删除设置为级联到关联的 PurchaseOrder 记录,只要它不与任何其他供应商报价相关联。
      • 从随机数生成器插入 po 号码是一个非常冒险的举动。实际上不要这样做。
      【解决方案3】:

      如果在插入行时生成了 SupplierQuoteId 和 PONumber,则两个“身份”列将被同步分配(3504 与 9553 一起,3506 与 9573 一起,3508 与 9593 一起,等等)。如果这个假设成立,那么您大概可以将 PONumber 设为计算列,如下所示:

      CREATE TABLE SupplierQuote 
      ( 
      supplierQuoteID int NOT NULL identity (3504,2) CONSTRAINT supquoteid_pk PRIMARY KEY, 
      PONumber AS (10 * supplierQuoteID - 25487)
      . 
      . 
      . 
      ); 
      

      我将supplierQuoteId 设为NOT NULL,这样可以确保PONumber 也不会为NULL。同样,您不再需要 PONumber 上的唯一约束,因为它始终是唯一的。 (如果您需要索引以提高性能,则可以在计算列上构建索引。)

      【讨论】:

        【解决方案4】:

        我想我会使用触发器来填充“第二个身份”。

        【讨论】:

          【解决方案5】:

          如果每个供应商报价只有一个 PO id,那么为什么不简单地使用供应商报价 ID 作为 PO id?

          如果可以有多个,则必须有一个带有外键约束的单独表。您当然可以使用级联删除从该表中删除,但如果您删除太多记录(导致锁定),或者我个人不想删除供应商报价,如果已创建采购订单编号,这意味着引用的项目实际上是购买的。您永远不想破坏实际购买的东西的记录。由于每个报价您可能会有多个 POS(我得到了六件商品的报价,首先购买了其中三件,然后在下周购买了另外两件),并且由于您可能想要存储有关采购订单的特定信息,所以我推荐一个单独的表。从长远来看,做任何其他事情都会给你带来麻烦。

          【讨论】:

            【解决方案6】:

            绕过非标识列中的自动增量。(MS SQL)虽然我认为这不是最佳实践!只是一个快速修复解决方案。

                INSERT INTO [dbo].[Employee]
                       ([EmpID]
                       ,[Name]
                       ,[Salary]
                       ,[Address]
                       ,[datecoded])
                 VALUES
                       ( (select top 1 EmpID from dbo.Employee order by EmpID desc) + 1
                       , 'name_value'
                       , 123456
                       ,'address_value'
                       , GETDATE())
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-06-19
              • 2014-12-07
              • 1970-01-01
              • 1970-01-01
              • 2014-04-03
              • 1970-01-01
              • 2012-07-31
              • 2012-12-14
              相关资源
              最近更新 更多