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

时间:2017-07-10 06:40:33

标签: sql-server

我有一个如下定义的Valuations表: -

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列不为空。 对于给定的ValuationDate,该行必须是唯一的(不存储时间)。 将来可能会添加更多FKs

SQL Server很可能是SQL 2014 Sql Express,但也可以使用Azure。

我计划从Upserts开始定期Temp table,每次可能包含数千行。 Valuations表不会被修剪,因此可以创建图表,显示随时间的估值,所以我最终预计会有数百万行。

只有我的应用程序才能写入数据库,所以理论上,如果有帮助,我可以在应用程序级别保持完整性。

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

2 个答案:

答案 0 :(得分:0)

尝试这种方法;

            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个NULL列。

答案 1 :(得分:0)

关于此要求

  

这个想法是只有一个FK列在a中不为null   给定的行。对于给定的ValuationDate,该行必须是唯一的(没有时间   存储)。

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

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

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 
) 

并且也遵循UNIQUE索引

CREATE UNIQUE INDEX IUN_Valuations_ValuationDate_AssetID_LiabilityID_ProviderFundID_ClientFundID
ON dbo.Valuations (ValuationDate, AssetID, LiabilityID, ProviderFundID, ClientFundID)
INCLUDE (Value)

[2]第二种解决方案是使用type-subtype / superclass-subclass方法:

[2.1]类型表将保留所有常用列:

dbo.Object(ID PRIMARY KEY, Type, ... common columns ... ) 
+ 
CREATE UNIQUE INDEX ... ON dbo.(ID, Type)

其中Type = {1 = Asset,2 = Liability,3 ...}

每个类型的

和[2.2]我将创建一个单独的表,其中只包含特定的列):

dbo.Asset(ID PK + FK, Type, ... specific columns to assets ...)
+
ALTER TABLE dbo.Asset
ADD CONSTRAINT ...
FOREIGN KEY (ID, Type)
REFERENCES dbo.Object(ID, Type)

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)