我的数据有点像......
Elements
Class | Synthetic ID (pk)
A | 2
A | 3
B | 4
B | 5
C | 6
C | 7
Elements_Xref
ID (pk) | Synthetic ID | Real ID (fk)
. | 2 | 77-8F <--- A class
. | 3 | 30-7D <--- A class
. | 6 | 21-2A <--- C class
. | 7 | 30-7D <--- C class
所以我将这些元素分配给合成ID并分组到类中。但是这些合成ID然后与我们实际关心的Real ID
配对。还有一个约束条件是Real ID
不能在单个类中重复出现。如何在一个连贯的设计中捕获所有这些?
我不想将Real ID
塞进上表,因为
Real ID
应该是什么。)显然,这可以通过充当约束的触发器来完成,但我想知道这是否可以使用常规约束/唯一索引来实现。使用 SQL Server 2005 。
我考虑过有两个主表SyntheticByClass
和RealByClass
,然后将这些表的ID放到另一个外部参照/链接表中,但这仍然不能保证两个元素的类比赛。也可通过触发器解决。
编辑:这是关键字填充,但我认为它与规范化有关。
编辑^ 2:如下面的评论所示,我似乎暗示外键不能为空。哪个是假的,他们可以!但是,无法做到的是在NULL重复的字段上设置唯一索引。尽管唯一索引支持NULL值,但它们不能约束集合中的多个NULL。由于Real ID
赋值最初是稀疏的,因此每个类的多个NULL Real ID
更有可能。
编辑^ 3:删除了多余的Elements.ID
列。
编辑^ 4:一般观察。似乎有三种主要方法在起作用,其中一种我已经提到过。
Class
字段添加到Xref
表。在(Class + Real ID)上创建一个UNIQUE约束,在(Class + Synthetic ID)上创建一个外键约束回到Elements
表。答案 0 :(得分:1)
您希望能够做的是表示Elements和Elements_Xref的连接对Class和Real ID有唯一约束。如果你有一个支持SQL-92 ASSERTION约束的DBMS,你可以这样做。
AFAIK,没有DBMS支持它们,所以你很难使用触发器。
设计并没有将Real ID限制为在类之间是唯一的,这似乎很奇怪;从讨论中可以看出,给定的Real ID可能是几个不同类的一部分。如果真实ID是“唯一的,除非为空”,那么如果DBMS支持“独特的除非”概念(大多数不支持;我相信有一个可以做到,但我忘记了),那么你将能够更容易地强制执行唯一性它是)。
这个问题排除了“干扰”上表中的Real_ID(元素);它不排除在下表(Elements_Xref)中包含Class,然后允许您在Elements_Xref中创建Class和Real_ID的唯一索引,从而实现(我相信)所需的结果。
从样本数据中不清楚Elements表中的合成ID是否唯一,或者它是否可以用不同的类重复(或者,实际上是否可以在单个类中重复合成ID)。鉴于似乎有一个ID列(可能是唯一的)以及Synthetic ID列,假设有时合成ID重复似乎是合理的 - 否则表中有两个唯一的列没有很好的理由。在大多数情况下,它并不重要 - 但如果将类复制到Elements_Xref表,它确实会影响唯一性约束。还有一种可能性;也许在Elements表中根本不需要Class;它应该只存在于Elements_Xref表中。我们没有足够的信息来判断这是否可能。
现在Elements表将Synthetic ID作为主键,事情变得更容易一些。有评论称“班级”信息实际上是“月份”,但我会试着忽略这一点。
在Elements_Xref表中,我们有一个唯一的ID列,然后是一个Synthetic ID(未标记为Elements的外键,但可能实际上必须是一个),以及Real ID。我们可以从示例数据中看到,多个Synthetic ID可以映射到给定的Real ID。目前尚不清楚为什么Elements_Xref表同时具有ID列和Synthetic ID列。
我们不知道单个合成ID是否只能映射到单个Real ID,或者它是否可以映射到多个Real ID值。
由于Synthetic ID是Elements的主键,我们知道单个Synthetic ID对应于一个Class。
我们不知道Synthetic ID到Real ID的映射是否随时间而变化(可能是Class与日期相关),以及是否必须记住旧状态。
我们可以假设表格减少到最低限度,并且每个表格中还有其他列,其内容并不直接与问题相关。
问题表明Real ID是其他数据的外键,可以为NULL。
我无法看到完美无冗余的设计。
我认为Elements_Xref表应该包含:
with(Synthetic ID,Class)作为引用Elements的'外键',Real ID上的NOT NULL约束,以及(Class,Real ID)上的唯一约束。
Elements_Xref表仅包含已知Real ID的行 - 并正确执行所需的唯一性约束。
奇怪的是,Elements_Xref中的(Synthetic ID,Class)数据必须与Elements中的相同列匹配,即使Synthetic ID是Elements的主键。
在IBM Informix Dynamic Server中,您可以实现此目的:
CREATE TABLE elements
(
class CHAR(1) NOT NULL,
synthetic_id SERIAL NOT NULL PRIMARY KEY,
UNIQUE(class, synthetic_id)
);
CREATE TABLE elements_xref
(
class CHAR(1) NOT NULL,
synthetic_id INTEGER NOT NULL REFERENCES elements(synthetic_id),
FOREIGN KEY (class, synthetic_id) REFERENCES elements(class, synthetic_id),
real_id CHAR(5) NOT NULL,
PRIMARY KEY (class, real_id)
);
答案 1 :(得分:1)
你可以
在Elements_Xref
Elements
和Synthetic ID
的结果集中的视图
在class
和[Real ID]
上添加唯一约束。在其他新闻中,这也是通过索引视图在MSSQL中执行功能索引的方式。
这是一些sql:
CREATE VIEW unique_const_view AS
SELECT e.[Synthetic ID], e.Class, x.[Real ID]
FROM Elements AS e
JOIN [Elements_Xref] AS x
ON e.[Synthetic ID] = x.[Synthetic ID]
CREATE UNIQUE INDEX unique_const_view_index ON unique_const_view ( Class, [Real ID] );
现在,显然,我不知道这个解决方案在Microsoft-land-place中不起作用,因为MS SQL Server重复的空值会违反UNIQUE约束:这违反了SQL规范。 This is where the problem is discussed about
这是Microsoft的解决方法:
create unique nonclustered index idx on dbo.DimCustomer(emailAddress)
where EmailAddress is not null;
不确定那是2005年还是2008年。
答案 2 :(得分:1)
我会:
此时我们确信Elements_Xref.Class始终与Elements.Class匹配。
现在我们需要实现“非空时唯一”逻辑。点击链接并滚动到“使用计算列实施复杂业务规则”部分: Indexes on Computed Columns: Speed Up Queries, Add Business Rules
或者,您可以在WHERE子句中使用WHERE RealID IS NOT NULL在(Class,RealID)上创建索引视图 - 这也将强制执行“非空时唯一”逻辑。
答案 3 :(得分:1)
为Elements_Xref创建索引视图,其中Real_Id不为空,然后在该视图上创建唯一索引
Create View Elements_Xref_View With SchemaBinding As
Select Elements.Class, Elements_Xref.Real_Id
From Elements_Xref
Inner Join Element On Elements.Synthetic_Id = Elements_Xref.Synthetic_Id
Where Real_Id Is Not Null
Go
Create Unique Clustered Index Elements_Xref_Unique_Index
On Elements_Xref_View (Class, Real_Id)
Go
除了模拟正确处理空值的唯一索引之外,这没有任何其他用途,即null!= null
答案 4 :(得分:0)
我认为触发器是您的最佳选择。约束不能交叉到其他表来获取信息。使用唯一索引也是如此(虽然我认为可能有索引的物化视图),但它们在表中是唯一的。当您将触发器放在一起时,请记住以基于集合的方式进行,而不是逐行进行,并使用多行插入和多行更新进行测试,其中真实密钥在数据集中重复。
答案 5 :(得分:0)
我认为您的两个原因中的任何一个都不会将Real ID
放入Elements
。如果给定元素具有0或1 Real ID
s(但绝不超过1),则它应该绝对位于Elements
表中。这样就可以限制Class
内的唯一性(我认为)。
你可以扩展两个不这样做的理由吗?
答案 6 :(得分:0)
使用字段Real ID,Class和Synthetic ID创建一个新表real_elements,主键为Class,RealId,并在实际添加RealID时添加元素
这会将实际ID限制为类的唯一,并为您提供一种方法,将类和实际ID与合成ID匹配
至于Real ID是外键,你的意思是如果它是两个类,那么键入它的数据将是相同的。如果是,则添加具有键Real Id的另一个表。这个密钥是一个外键到real_elements和任何其他需要真实ID作为外键的表