如何在关系数据库中最好地存储数字列表?

时间:2009-07-06 15:02:47

标签: database-design types

我想在关系数据库中存储一个数字列表(基本上是数学术语中的set),特别是SQL Server 2005。

理想情况下,我希望它是给定表上的单个列,但我愿意听到任何解决方案。我需要存储的数据就像我说的那样,是一组数字。

  • 不需要是顺序的(即间隙是正常的,正常的,典型的)
  • 范围是可能的(即1 - 4)但是我希望以这种方式显示它我可以使用快捷方式来存储它
  • 它也可以是“all”,因此对于这种“无限”的情况,必须保留至少一个值,最好是逻辑上
  • 数字列表不需要按顺序排列(即3,2,9,5),但最好也是完全合理的,它们将在插入之前进行排序,因为只有代码才能进行插入,而不是手动用户。不过,它可能不应该依赖或期望列表已经排序。
  • 这组数字应该可以轻松搜索到一个子集(见下文)
  • 所有数字都应该是不同的(没有欺骗),但这可以并且将在插入之前强制执行

此列用于存储该行适用的给定流程的所有“步骤编号”。因此,每行可以以任何顺序,范围或顺序应用于一个或多个步骤。可能的最大步数(最大范围,基本上)在行与行之间是不同的,但我高度怀疑它们中的任何一个都会达到数百个,因此在99.9%的情况下,最大值不应超过20或30,而我如果有任何接近100的话,我会感到惊讶。每一行都保证最少有一个值(步骤)(即没有任何步骤适用于任何步骤没有意义),但我这就像将列设置为not null一样简单。

然而,它存储,我希望它很容易搜索。例如,我宁愿不必通过大量的箍来编写SQL查询来查找适用于“步骤3”的所有行。如果给定的行有几个适用的步骤(例如,2,3,7和8),那么在按步骤3搜索时,匹配它应该不会太难。

另外,虽然我希望在查看原始数据时能够产生某种逻辑意义(对于任何需要在系统上工作的人,我不在后问,因此他们不必阅读厚厚的文档,以找出我的模糊编码),我愿意妥协。因此,将列表编码为可以被可靠解码的内容是可以接受的。

我道歉,如果这是一个骗局 - 我一直在谷歌上搜索,但我怀疑我的这个问题不知道要搜索什么或如何短语或称之为找到我正在寻找的东西。

在更多的注释中,我想知道这不是关系数据库不足的领域之一。不幸的是,我在这里没有选择。我必须将它存储在SQL Server中。单独保存到文件或其他持久性数据存储是不可能的,我担心。

7 个答案:

答案 0 :(得分:4)

我不记得正确的术语,但正确的方法是创建一个如下表所示的表:

|  id  |  table1_id  |  value  |
--------------------------------
|   0  |          1  |      1  |
|   1  |          1  |      2  |
|   2  |          1  |      3  |
|   3  |          1  |      7  |
|   4  |          1  |      9  |
|   5  |          2  |      1  |
|   6  |          2  |      3  |
| ...  |        ...  |    ...  |

对于table1中的每个值,您需要将所需的值添加到此表中。

对于'all',你可以在table1中创建一个列,如果你想要全部,你可以设置一个标志。 (我在MySql中使用'enum',但我不确定它是否存在于SQL Server中)。

我不确定是否有一些特定于Sql Server的方法,因为我主要使用MySql。

答案 1 :(得分:2)

为什么附加表步骤(processID JOIN,步骤INT)不是一个选项? 我很确定这是最容易维护/编码的。

SELECT process.name FROM process, steps WHERE process.id = steps.processID AND steps.step = 3;

原谅我的SQL,但已经有一段时间了:)

编辑:UNIQUE(processID, step)是可取的。

答案 2 :(得分:1)

我使用简单且规范的关系设计:CREATE TABLE范围(process_id int,num_low int,num_hi int)。后两列指定范围。每列独立索引。对于“特殊”无穷大值,只需使用maxints或其他布尔列。

优点:轻松搜索特定数字是否在范围内,或范围是否相交。易于维护。一般可理解性和简单性。

缺点:修改集合时需要一些逻辑,即检查新插入或修改的范围是否相交。可能需要拼接范围。

答案 3 :(得分:1)

下面做一个子表(MitMaro)的答案是“标准”方式。

如果必须将一组数字放在一列或一个表中,尽管我可以想象的唯一方法是使用按位运算来存储集合,您可以在数据查询中使用按位运算来查找正在设置的特定位。快速谷歌搜索表明MSSql 2005支持这个,但最多只支持32位int,所以如果你通过32步,你将遇到问题。

总而言之,子表格是针对表格进行更易理解的查询所能达到的最高标准。这也是最安全的,可以支持任何未来大于32个值映射的情况。

答案 4 :(得分:1)

如果你不依赖于SQL Server,Postgresql通过array对这类事情有很大的支持。它们甚至对无限具有特殊价值。

如果你与SQL Server绑定,那么MitMaro最好。

答案 5 :(得分:1)

create table setmember (setid int, setmemberid int)
create unique nonclustered index idx_setmember_idx1 on setmember (setid, setmemberid)

让我假设“全部”的幻数(-1或999999999)。

这对于基于每个集的查询和通过非聚集索引更新插入将是高度高效的。唯一性强制不重复条目。将“所有”或多个集合成员强制实施为约束是有问题的,但是虽然可以在触发器中完成,但是收益递减。

另外添加

create nonclustered index idx_setmember_idx2 on setmember (setmemberid, setid)

允许有效的反向查询查询。

如果使用数组类型,则可能无法实现有效的反向查找。

注意上面的所有SQL都符合ANSI标准。

答案 6 :(得分:1)

使用solution to a similar question结束。

尽管如此,谢谢!我喜欢阅读每个人对这些深奥的数据库设计领域的看法。