Sql server 多个空列的最佳索引/约束

Sql server 多个空列的最佳索引/约束,sql-server,Sql Server,我的估价表定义如下:- ID (PK, int, not null) AssetID (FK, int, null) LiabilityID (FK, int, null) ProviderFundID (FK, int, null) ClientFundID (FK, int, null) ValuationDate (date, not null) Value(money, not null) 其思想是给定行中只有一个FK列不为空。 此外,对于给定的估价日期(不

我的估价表定义如下:-

ID (PK, int, not null)  
AssetID (FK, int, null)  
LiabilityID (FK, int, null)  
ProviderFundID (FK, int, null)  
ClientFundID (FK, int, null)  
ValuationDate (date, not null)  
Value(money, not null)  
其思想是给定行中只有一个
FK
列不为空。 此外,对于给定的
估价日期
(不存储时间),该行必须是唯一的。 将来可能会添加更多的
FKs

SQL server可能是SQL 2014
SQL Express
,但也可能使用Azure

我计划从一个
Temp表
中定期执行
Upserts
,该表一次可能包含数千行。估价表不会被删减,这样就可以创建图表来显示一段时间内的估价,所以我预计最终会有数百万行

只有我的应用程序会写入数据库,因此理论上,如果有帮助的话,我可以在应用程序级别保持完整性

我应该如何对此表应用索引/约束以保持其性能? (如果你认为这种设计不是最好的,欢迎提出其他建议)

试试这种方法

            create table dbo.Valuations
                (
                ID int identity(1,1),
                DataTypeId tinyint,
                UniqueId int,
                ValuationDate date,
                Value money
                )
            go
            create table dbo.DataType
                (
                DataTypeId int,
                Data varchar(100)
                )
            go
            insert into dbo.DataType
            select 1,'Asset'
            insert into dbo.DataType
            select 2,'Liability'
            insert into dbo.DataType
            select 3,'ProviderFund'
            insert into dbo.DataType
            select 4,'ClientFund'
            go
            -- Now insert an 'asset' (for example) like this;
            insert dbo.Valuations(DataTypeId,UniqueId,ValuationDate,Value)
            select
                DataTypeId=1, -- this lookups the correct 'type' in the 'dbo.DataType' table
                UniqueId=98,-- whatever this is
                ValuationDate='20170725',
                Value=88.99

这样,您就可以准确地捕获所需的数据。不需要总是有3个空列。

关于此要求

其思想是,在一个数据库中,只有一个FK列不为null 给定行。此外,对于给定的估价日期(无时间),行必须是唯一的 已存储)

我将使用以下解决方案之一:

[1] 保持当前设计,我将定义以下检查约束:

ALTER TABLE dbo.Valuations 
ADD CONSTRAINT CK_Valuations_CheckForeignKeysNULLability
CHECK (
AssetID IS NOT NULL AND LiabilityID IS NULL AND ProviderFundID IS NULL AND ClientFundID IS NULL  
OR
AssetID IS NULL AND LiabilityID IS NOT NULL AND ProviderFundID IS NULL AND ClientFundID IS NULL  
OR
AssetID IS NULL AND LiabilityID IS NULL AND ProviderFundID IS NOT NULL AND ClientFundID IS NULL  
OR
AssetID IS NULL AND LiabilityID IS NULL AND ProviderFundID IS NULL AND ClientFundID IS NOT NULL 
) 
并遵循唯一索引

CREATE UNIQUE INDEX IUN_Valuations_ValuationDate_AssetID_LiabilityID_ProviderFundID_ClientFundID
ON dbo.Valuations (ValuationDate, AssetID, LiabilityID, ProviderFundID, ClientFundID)
INCLUDE (Value)
[2] 第二种解决方案是使用类型子类型/超类子类方法,因此:

[2.1]类型表将保留所有公共列:

dbo.Object(ID PRIMARY KEY, Type, ... common columns ... ) 
+ 
CREATE UNIQUE INDEX ... ON dbo.(ID, Type)
其中类型={1=资产,2=负债,3…}

[2.2]对于每种类型,我将创建一个单独的表,其中仅包含特定列):

等等

和估价表:

dbo.Valuations(ID PK, IDObject - FK, ValuationDate, Value)
+
CREATE UNIQUE INDEX ... ON dbo.Valuations (ValuationDate, IDObject)
INCLUDE (Value)

对于空列,请使用
稀疏列
属性:谢谢你的主意。然而,在我的例子中,我使用LLBLGen并使用预取路径(可选)在获取某个项目时返回该项目的估价,而该项目需要FKs。
dbo.Liability(ID PK + FK, Type, ... specific columns to liabilities ...)
+
ALTER TABLE dbo.Liability
ADD CONSTRAINT ...
FOREIGN KEY (ID, Type)
REFERENCES dbo.Object(ID, Type)
dbo.Valuations(ID PK, IDObject - FK, ValuationDate, Value)
+
CREATE UNIQUE INDEX ... ON dbo.Valuations (ValuationDate, IDObject)
INCLUDE (Value)