我正在尝试为“分配给事物的序列号”建模。我想将序列号视为由较小的数字或字符组成的单位-因此,诸如“ AB12CD”的序列号将存储为三元组("AB", 12, "CD") :: (varchar, int, varchar)
。序列号可以具有任意数量的组件(尽管可能的值仅在2到6之间),并且这些组件将始终匹配(\d+)|([a-z]+)
。这里的目的是帮助诸如“组件N在i和j之间的所有事物”之类的查询,而不必在每一行上进行字符串操作(在某些分隔符上拆分,解析ints,跟踪序数)。
我遇到的问题是,我想在数据库中强制执行序列号唯一性,但是按照我目前的想法,我看不到到达那里的方法。该表是这样的:
thing_id | component | char_part | num_part
------------------------------------------
1 | 1 | "AB" | null
1 | 2 | null | 12
2 | 1 | "AB" | null
2 | 2 | null | 12
因此在上表中,事物1和事物2在概念上均分配有序列号“ AB12”。具有唯一约束的索引视图可以解决此问题,但是我必须使用CTE来递归地按序添加普通对象,而索引视图中的CTE是不可能的。如果我可以在索引视图中进行CTE,则可以对以下内容建立索引,并对“ SN”应用唯一的约束,这将被违反并且生活会很美好:
thing_id | SN
------------------
1 | "AB12"
2 | "AB12"
是否有为此建议的模式,或强制执行“多行唯一性”的方法?我希望不必手动保持两个表同步(一个带有组合字符串值,一个带有切碎的组件)。
我从此开始,陷入混乱,最后提出的问题多于答案。对于那个很抱歉。将任何人发布为“外部讨论”可能会帮助您找到解决问题的正确方法。
根据您的发言,我认为这是一个标准化问题。按照这种方式处理,我提出了以下内容,这可能并不是您想要的。沿途留下名字…
CREATE TABLE dbo.Component
(
Component varchar(10) not null primary key
)
表组件中的样本数据:
AB
CD
12
34
(我不确定这与您的char_part
和num_part
值如何相关;我假设每个组件都有唯一的标识符。如果您对不同类型的组件使用不同的识别码,则您有一个更复杂的问题。)
接下来,表Thing,它是通过Components进行构建/组装的,仍然是它自己的,呃,东西,因此需要它自己的正确规范化的每行一件事表:
CREATE TABLE dbo.Thing
(
ThingId int not null identity(1,1) primary key
)
样本数据:
1
2
3
4
接下来,什么将事物与组件联系起来?多对多桌子!
CREATE TABLE dbo.ThingComposition
(
ThingId int not null
,Component varchar(10) not null
,primary key clustered (ThingId, Component)
)
有数据
1, AB
1, 12
2, AB
2, 23
3, AB
4, CD
4, 12
4, 34
此结构或类似的结构应支持切片要求的搜索
以上数据将产生序列号,例如:
1 AB12
2 AB23
3 AB
4 CD1234
但是,我认为SQL中没有任何合理的*和声明性内容,使您无法在ThingComposition表中包含以下内容:
1, AB
1, 12
5, AB
5, 12
在很大程度上还取决于您如何从基本组件代码构造序列号,这在您的描述中并不清楚。 “ AB12”和“ 12AB”都是有效的序列号吗?还会出现更多问题-随着时间跨多个表添加,更新和删除行时,您如何强制序列号唯一性?如果您有“ AB12”,如果必须一次添加一行,该如何添加“ AB1234”?您是否“构建”事物,然后翻转一点(IsLive)说“完成,现在强制执行唯一性”? (可以完成-过滤后的唯一索引。)序列号(事物中的组件)是否会随时间变化?头脑令人困惑。
我打算建议
CREATE TABLE Thing
(
ThingId int not null identity(1,1) primary key
,SerialNumber varchar(100) not null -- enough characters?
)
在SerialNumber上具有唯一索引,并精心构造了应用程序代码,以使用正确的SerialNumber构造并填充它,但是,是的,这很快变得很复杂。我最终遇到了许多悬而未决的问题,无法回答。希望其他人提出一个更好的主意!
*触发器不合理。不要使用触发器。