作为 PK 的一部分,包含日期和数字的计算列可以为空,但不能同时为空

Calculated column with date and number, either but not both can be null, as part of PK

我有一个 table 创建于 1990 年(是的,27 年前),它有一个代理 PK 和很多重复的行。我正在将 table 从 Access 迁移到 SQL 服务器,并且我已经删除了代理键字段,但我试图弄清楚如何从两个源列中包含一个计算列,这可以包含空值。 这对我有用:

CREATE TABLE [dbo].[ActionHistory]
(
    [Position Number] [int] NOT NULL,
    [SSN] [nvarchar](11) NOT NULL,
    [Action] [nvarchar](10) NOT NULL,

    [EffectiveSalaryKey] AS  (CONVERT([varchar](20), [Action Effective Date], 20) + ';' + 
                              CONVERT([varchar](20), isnull([Salary], ''), 0)) PERSISTED NOT NULL,
    [Action Effective Date] [datetime] NULL,
    [Salary] [money] NULL,
    ...,
    [entered] [datetime] NULL 
         CONSTRAINT [DF_ActionHistory_entered]  DEFAULT (getdate()),

    CONSTRAINT [PK_ActionHistory] 
        PRIMARY KEY CLUSTERED ([Position Number] ASC, [SSN] ASC, [Action] ASC, [EffectiveSalaryKey] ASC)
    ...
)

但它不允许我输入无效日期的行。

我想做一些事情,比如将空日期转换为键字段的空白,甚至是像 1/1/1900 00:00:00 这样的静态值,但我无法获得正确的语法。

我尝试在转换为 varchar 之前添加 isnull(date,''),在转换之后,以及在附加定界符之后添加,但它们没有用,我也尝试添加 isnull(date,'1900-01-01 00:00:00') 但这也没有用。

当我尝试时:

[EffectiveSalaryKey]  AS 
    (
        CONVERT(
            [varchar](20),isnull([Action Effective Date],''),20
                )

它说:

Computed column 'EffectiveSalaryKey' in table 'ActionHistory' cannot be persisted because the column is non-deterministic.

我正在 GUI 之外使用脚本来执行此操作,据我所知,此类分配存在一个错误。我也明白从日期转换为 varchar 时必须提供样式。

请告诉我应该如何附加这些字段值,以便我可以将计算列用作 PK 的一部分。

谢谢,

-贝丝

我建议在此 table 上也使用代理键,并补充唯一索引。 (连同用下划线替换列名中的空格)

对于您的计算列,我认为这就是您所追求的:

  , effectivesalarykey  as (
      isnull(convert(varchar(20),[action_effective_date],20)+ ';','')
      + isnull(convert(varchar(20),salary),'0')
    ) persisted not null

第一个isnull中的第一个''可以改成任何你喜欢的

  , effectivesalarykey  as (
      isnull(convert(varchar(20),[action_effective_date],20)+ ';','1900-01-01 00:00:00;')
      + isnull(convert(varchar(20),salary),'0')
    ) persisted not null

rextester:http://rextester.com/SBA4540

create table dbo.actionhistory(
    id int not null identity(1,1)
  , position_number int not null
  , ssn nvarchar(11) not null
  , action nvarchar(10) not null
  , effectivesalarykey  as (
      isnull(convert(varchar(20),[action_effective_date],20)+ ';','')
      + isnull(convert(varchar(20),salary),'0')
      ) persisted not null
  , 
    [action_effective_date] datetime null
  , salary money null
  , entered datetime null constraint df_actionhistory_entered  default (getdate())
  , constraint pk_actionhistory primary key clustered (id)
);

create unique nonclustered index ix_actionhistory_position_ssn_action_effectivesalarykey 
  on dbo.actionhistory (
      position_number asc
    , ssn asc
    , action asc
    , effectivesalarykey asc )


insert into dbo.actionhistory (position_number,ssn,action) values 
(1,'000-00-0000','Test')

select * 
from dbo.actionhistory;

结果:

+----+-----------------+-------------+--------+--------------------+-----------------------+--------+---------------------+
| id | position_number |     ssn     | action | effectivesalarykey | action_effective_date | salary |       entered       |
+----+-----------------+-------------+--------+--------------------+-----------------------+--------+---------------------+
|  1 |               1 | 000-00-0000 | Test   |                  0 | NULL                  | NULL   | 13.02.2017 20:35:21 |
+----+-----------------+-------------+--------+--------------------+-----------------------+--------+---------------------+