根据您的编辑,您可以在资产表上引入一个超级键并使用各种约束来强制执行您正在寻找的大部分内容:
create table Asset (
AssetID int not null primary key,
AssetTypeID int not null
--Skip all of the rest, foreign keys, etc, irrelevant to example
,constraint UQ_Asset_TypeCheck
UNIQUE (AssetID,AssetTypeID) --This is the superkey
)
以上意味着该AssetTypeID
列现在可以在其他表中检查/强制执行,并且不存在不一致的风险
create table Servers (
AssetID int not null primary key,
AssetTypeID as 1 persisted,
constraint FK_Servers_Assets FOREIGN KEY (AssetID)
references Asset (AssetID), --Strictly, this will become redundant
constraint FK_Servers_Assets_TypeCheck FOREIGN KEY (AssetID,AssetTypeID)
references Asset (AssetID,AssetTypeID)
)
因此,在上面,我们强制此表中的所有条目实际上必须是正确的资产类型,方法是使其成为一个固定的计算列,然后在外键中使用返回到超键。
--So on for other asset types
create table Asset_IP (
AssetID int not null,
IPAddress int not null primary key, --Wrong type, for IPv6
AssetTypeID int not null,
constraint FK_Asset_IP_Assets FOREIGN KEY (AssetID)
references Asset (AssetID), --Again, redundant
constraint CK_Asset_Types CHECK (
AssetTypeID in (1/*, Other types allowed IPs */)),
constraint FK_Asset_IP_Assets_TypeCheck FOREIGN KEY (AssetID,AssetTypeID)
references Asset (AssetID,AssetTypeID)
)
现在,在上面,我们再次引用超级键以确保我们有一个本地(此表)正确的AssetTypeID
值,然后我们可以在检查约束中使用它来限制哪些资产类型实际上是该表中允许的条目。
create unique index UQ_Asset_SingleIPs on Asset_IP (AssetID)
where AssetTypeID in (1/* Type IDs that are only allowed 1 IP address */)
最后,对于某些AssetTypeID
值,我们确保该表仅包含一行AssetID
。
我希望这能给您足够的想法,让您了解如何根据类型实现各种检查。如果您愿意/需要,您现在可以构建一些视图(其余代码将通过这些视图进行交互),这些视图隐藏了额外的列并提供触发器来简化INSERT
语句。
在旁注中,我建议在表命名时选择一个约定并坚持它。我的首选是使用复数/集体名称,除非该表仅打算包含一行。所以我会重命名Asset
为Assets
,例如,或Asset_IP
作为Asset_IPs
。目前,你有一个混合物。