Sql 强制从一个表到任何表的引用完整性
我有许多表示业务对象的表,例如产品、人员、位置,我想添加一个标记表(如在分类法中) 如何允许将多个标记应用于多种类型的实体,从而允许DBMS强制执行引用完整性,而不需要这样的链接表:Sql 强制从一个表到任何表的引用完整性,sql,sql-server,database-design,Sql,Sql Server,Database Design,我有许多表示业务对象的表,例如产品、人员、位置,我想添加一个标记表(如在分类法中) 如何允许将多个标记应用于多种类型的实体,从而允许DBMS强制执行引用完整性,而不需要这样的链接表: CREATE TABLE TagUse ( tagId bigint, productId bigint NULL, personId bigint NULL, locationId bigint NULL, ... whateverId bigint
CREATE TABLE TagUse (
tagId bigint,
productId bigint NULL,
personId bigint NULL,
locationId bigint NULL,
...
whateverId bigint NULL
)
或者更糟:
CREATE TABLE PersonTags (
tagId bigint,
personId bigint
)
CREATE TABLE LocationTags (
tagId bigint,
locationId bigint
)
...
CREATE TABLE WhateverTags (
tagId bigint,
whateverId bigint
)
我刚刚想到了第三种选择:与其为每个实体拥有单独的*标记
表,不如将每个实体看作是从“Taggable
”继承的,然后子表引用该表:
CREATE TABLE Taggable (
taggableId bigint,
tagId bigint
)
CREATE TABLE Persons (
personId bigint,
...
taggableId bigint
)
您可以使用序列对象:
CREATE TABLE [TaggableObjects] (
objectId BIGINT IDENTITY(1,1)
)
CREATE TABLE [Persons] (
objectId BIGINT, -- referencing Objects.objectId
name VARCHAR(50)
)
CREATE TABLE [Locations] (
objectId BIGINT, -- referencing Objects.objectId
country VARCHAR(50)
)
在Java
和C#
等编程语言中,可以调用Persons
和Locations
作为TaggableObject
的扩展
接下来,您可以将标记实现为:
CREATE TABLE [Tags] (
tagId BIGINT IDENTITY(1,1),
objectId BIGINT
)
尽管像这样的实现的问题是,您必须找出识别Tags.objectId是什么类型的最佳方法
请注意,根据要使用的引擎的不同,许多支持某种功能以更轻松地实现序列对象,您可能希望直接使用它。这两种可能性都优于您想要做的事情。因为没有办法使您想要的设计具有引用完整性。坦率地说,这是一个SQL反模式。坦白地说,我更喜欢第二种,但我想到了第三种选择。
CREATE TABLE [Tags] (
tagId BIGINT IDENTITY(1,1),
objectId BIGINT
)