具有日期和数字的计算列,或者不是两者都可以为空,作为PK的一部分

时间:2017-02-13 19:21:46

标签: sql-server calculated-columns

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

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这样的静态值,但我无法正确理解语法。

我尝试在转换为isnull(date,'')之前添加varchar,转换后添加分隔符,但是它们不起作用,我也尝试添加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之外使用脚本执行此操作,因为据我所知,这种类型的赋值存在错误。我也理解在从date转换为varchar时必须提供样式。

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

谢谢,

-Beth

1 个答案:

答案 0 :(得分:1)

我建议在此表上使用代理键,并使用唯一索引进行补充。 (以及用下划线替换列名中的空格)

对于您的计算列,我认为这就是您的目标:

  , 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 |
+----+-----------------+-------------+--------+--------------------+-----------------------+--------+---------------------+