在postgres的同一列中存储不同数据类型的Sane方法?

K.N*_*zyk 9 postgresql database-design

我目前正在尝试修改与postgres数据库交互的现有API.简而言之,它基本上存储描述符/元数据,以确定实际的"资产"(通常是某种文件)存储在服务器的硬盘上的位置.

目前,可以使用任意数量的未定义键值对(即uploadedBy,addedOn,assetType等)"标记"这些"资产" .这些标记存储在一个单独的表中,其结构类似于以下内容:

+---------------+----------------+-------------+
|assetid (text) | tagid(integer) | value(text) |
|---------------+----------------+-------------|
|someStringValue| 1234           | someValue   |
|---------------+----------------+-------------|
|aDiffStringKey | 1235           | a username  |
|---------------+----------------+-------------|
|aDiffStrKey    | 1236           | Nov 5, 1605 |
+---------------+----------------+-------------+
Run Code Online (Sandbox Code Playgroud)

assetid和tagid是来自其他表的外键.可以想象表示文件的assetid,tagid/value对是描述符的映射.

现在,API(使用Java)将所有这些键值对创建为Map对象.这包括时间戳/日期等内容.我们想要做的是以某种方式能够为键值对中的值存储不同类型的数据.或者至少在数据库中以不同方式存储它,这样如果我们需要,我们可以运行查询来检查这些标签上的日期范围等.但是,如果它们作为文本项存储在数据库中,那么我们必须使用.)知道这实际上是一个日期/时间/时间戳项,并且b.)转换成我们可以实际运行的东西查询.

到目前为止我只能想到一个想法,没有完全改变过多地改变数据库的布局.

它是扩展assettag表(如上所示)以包含各种类型的附加列(数字,文本,时间戳),允许它们为空,然后在插入时,检查相应的"键"以确定哪种类型的数据它真的是.但是,我可以看到这种实现存在很多问题.

任何PostgreSQL-Ninjas都能提出如何解决这个问题的建议吗?我最近才回到数据库交互的深层,所以我承认我有点生疏.

Boh*_*ian 16

你基本上有两个选择:

选项1:稀疏表

每种数据类型都有一列,但只使用与您要存储的数据类型匹配的列.当然,这会导致大多数列无效 - 浪费空间,但纯粹主义者喜欢它,因为打字很强.有点笨拙,必须检查每列是否为null,以确定适用的数据类型.另外,如果你真的想存储一个null,那就太糟糕了 - 那么你必须选择一个"意味着空"的特定值 - 更笨拙.

选项2:两列 - 一列用于内容,一列用于类型

所有内容都可以表示为文本,因此具有值的文本列,以及该类型的另一列(int或text),因此您的应用程序代码可以在正确的类型对象中恢复正确的值.好东西是你可以轻松地将类型扩展到SQL数据类型之外的东西,并且你没有很多空值.

  • *选项 2* 中 *范围* 查询的索引怎么样?我认为使用选项 2 最终会得到一些无法有效查询的结果...... (2认同)

zak*_*zak 7

另一种选择,取决于你在做什么,可能是只有一个值列,但在值周围存储一些 json...

这可能看起来像:

  {
    "type": "datetime",
    "value": "2019-05-31 13:51:36" 
  } 
Run Code Online (Sandbox Code Playgroud)

甚至可以更进一步,使用JsonXML列。