我在DB(基于Postgres)中有一个表,它在面向对象编程中就像一个超类。它有一个列'type',用于确定表中应存在哪些附加列(子类属性)。但我不希望表包含所有可能的列(所有可能类型的所有属性)。
所以我决定制作一个表,包含'key'和'value'列(即'filename'='/ file',或'some_value'='5'),其中包含对象的任何可能属性,不包括在超类表中。并且还创建了一个相关表来包含可用的“键”值。
但是这种架构存在问题 - 默认情况下,'value'列应该是字符串数据类型,以便能够包含任何内容。但我不认为转换成字符串是一个很好的决定。绕过这个限制的最佳方法是什么?
答案 0 :(得分:10)
您正在尝试的设计是Entity-Attribute-Value的变体,它带来了很多问题和效率低下。除了作为最后的手段之外,这对你正在做的事情来说不是一个好的解决方案。
什么是更好的解决方案是fallen888描述的内容:为每个子类型创建一个“子类型”表。如果你有一个有限数量的子类型,这听起来就像你拥有的那样,这是可以的。然后,您的子类型特定属性可以包含数据类型,如果合适,还可以使用NOT NULL
约束,如果您使用EAV设计,这是不可能的。
子类表设计的另一个缺点是你不能强制在子类表中存在一行只是因为超类表中的主行说它应该。但这比EAV设计引入的更为温和。
编辑:关于您对任意实体的评论的其他信息,是的,这是一种非常常见的模式。谨防一种称为“多态关联”的破解解决方案,这是许多人在这种情况下使用的技术。
答案 1 :(得分:2)
相反如何......每个子类型都有自己的数据库表。 base / super表只有一个varchar列,它包含子类型DB表的名称。那么你可以有这样的东西......
Entity
------
ID
Name
Type
SubTypeName (value of this column will be 'Dog')
Dog
---
VetName
VetNumber
etc
如果您不希望您的(子)表名在基表中是varchar值,您也可以只有一个SubType表,其主键位于基表中。
答案 2 :(得分:0)
唯一的解决方法(保留您的结构)是使用单独的表:
create table IntProps(...);
create table StringProps(...);
create table CurrencyProps(...);
但我认为这不是一个好主意......
答案 3 :(得分:0)
一种常见的方法是让键值表包含多个列,每个数据类型一个,即StringValue,DecimalValue等。
只知道您正在为不需要更改的数据库架构交换可查询性和性能。您还可以考虑ORM映射或对象数据库。
答案 4 :(得分:0)
您可以拥有每种类型的键/值表。可用表需要对特定键/类型对的可用性进行编码,以指向正确键入的键/值表。
然而,对于基于行的关系数据库来说,这似乎是一种非常低效的架构。
也许您应该看一下面向列的关系数据库?
答案 5 :(得分:0)
感谢您的回答。我会更具体地解释一下我需要什么。 需要对博客+论坛网站进行编程,我一直在关注WordPress DB structure。
强烈需要能够对任何类型的“对象”发表评论,例如博客条目或视频文件附件。上面的数据库结构非常容易扩展并满足我们的所有需求是它选择的原因。
但改变它并不迟,因为这是在早期工程阶段。此外,我们的模型现在闻起来像一个完全基于树的层次结构的DB。现在我接受Bill Karwin's and fallen888 answers,但也许我的方向完全错误了?
答案 6 :(得分:0)
关于用户能够向表中添加新字段:
我很钦佩所有这些人发表评论。
几年前我曾经对这类事情感兴趣,但最近写了很少的代码(除了一点点PHP和MYSQL)。
我认为如果你想继续下去就没关系 - 你最终可能会有新的东西。
很抱歉给这个计划泼冷水 - 我很佩服你的努力。我个人的信念是,如果你朝这个方向走得足够远,你最终会得到一个比SQL更能解释自然语言的系统。 (1970年左右,SQL实际上拼写为Sequel,它实际上代表“结构化英语查询语言”,但是在它们在1970年代标准化之后 - 我想有人说Oracle是第一个商业实现,19079年,“英语”得到了下降,因为我猜他们认为它只是英语的一小部分。
我在这方面已经失去了动力,因为我没有找到工作。如果没有轻松的工作来支付账单,我可以尝试这些想法,有点难以专注于这个领域。
祝愿所有人。
答案 7 :(得分:0)