SQL Server计算列作为主键

时间:2015-07-13 11:37:35

标签: sql sql-server

我创建了一个以计算列为主键的表。 表创建得很好。这里是脚本..

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ARITHABORT ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [planning.A062].[RMAllocation](
    [Id] [int] IDENTITY(100,1) NOT NULL,
    [RMAllocatonId]  AS ('RMA_'+CONVERT([nvarchar](100),[Id])) PERSISTED NOT NULL,
    [RequsitionNo] [nvarchar](100) NULL,
    [RMDemandId] [nvarchar](104) NULL,
    [HierarchyId] [nvarchar](102) NULL,
    [Season] [nvarchar](50) NULL,
    [VendorSupplierNo] [nvarchar](100) NULL,
    [Year] [int] NULL,
    [Month] [int] NULL,
    [Week] [int] NULL,
    [Day] [int] NULL,
    [PlannedQty] [int] NULL,
    [ConfirmedQty] [int] NULL,
    [Status] [int] NULL,
    [CreatedBy] [int] NULL,
    [SyncId] [nvarchar](100) NULL,
    [CreatedOn] [datetime2](7) NULL,
    [UpdatedBy] [int] NULL,
    [UpdatedOn] [datetime2](7) NULL,
    [IsActive] [bit] NULL,
    [RecordDateTime] [datetime2](7) NULL,
 CONSTRAINT [PK_RMAllocation] PRIMARY KEY CLUSTERED 
(
    [RMAllocatonId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

问题是当我使用Designer View更改此表(添加/编辑列)时,它会给我以下错误。

enter image description here

错误

Unable to create index 'PK_RMAllocation'.  
Cannot define PRIMARY KEY constraint on nullable column in table 'RMAllocation'.
Could not create constraint. See previous errors.

当我使用脚本进行修改时,它可以工作。甚至我已将计算列声明为NOT NULL。怎么会发生这种情况?

4 个答案:

答案 0 :(得分:12)

评论太长了。设计师出了点问题。 SQL Server在文档中非常清楚,计算列可以用于主键(例如,here)。

我的猜测是,设计人员正在删除表中的所有约束并将其重新添加。最终以错误的顺序添加它们,因此主键在计算列的not null之前分配。除了显而易见的不使用设计师之外,我不知道是否有任何解决方法。

答案 1 :(得分:5)

根据the documentation(强调我的)

  

计算列不能用作DEFAULT或FOREIGN KEY   约束定义或使用NOT NULL约束定义

因此,即使在TSQL中也可以使用它,这有点令人惊讶。

当设计人员通过重新创建表来实现更改时,它会丢失列定义上的NOT NULL

[Id] [int] IDENTITY(100,1) NOT NULL,
[RMAllocatonId]  AS ('RMA_'+CONVERT([nvarchar](100),[Id])) PERSISTED,
[RequsitionNo] [nvarchar](100) NULL,

从语义上讲,NOT NULL常量和NOT NULL列的连接永远不会是NULL

另一种可以说服SQL Server列NOT NULL的方法 - 即使在没有NOT NULL的情况下也可以将定义包装在ISNULL中。

以下适用于设计师

[RMAllocatonId]  AS (ISNULL('RMA_'+CONVERT([nvarchar](100),[Id]),'')) PERSISTED 

答案 2 :(得分:0)

在插入时,系统不知道新的[id]值。您需要一个稍后更新该值的触发器。

答案 3 :(得分:0)

当两个Id值相同时,相应的RMAllocatonId值将相同。如果两个Id值不同,则相应的RMAllocatonId值将不同。因此,使Id唯一等同于使RMAllocatonId唯一。

如果你问我,只需将PRIMARY KEY放在它所属的Id上并完成它......