Sql 只有1或2个可选字段的数据库表。。。拆分成多个表?

Sql 只有1或2个可选字段的数据库表。。。拆分成多个表?,sql,database-design,Sql,Database Design,在我正在设计的数据库中,有一个相当中心的表,表示已经出售或正在出售的东西。它区分个人销售(如易趣)和正规公司的销售。这意味着字面上有1或2个字段并不同样适用于这两种情况。。。例如,一个字段仅在一种情况下使用,另一个字段在一种情况下是可选的,但在另一种情况下是强制性的。 如果有更多的特殊性,最好先有一个核心表,然后有两个表,其中包含与特定案例相关的字段。但是在这里,创建两个表只是为了包含一个字段加上对核心表的引用,这在美学上是不好的,对查询设计器和DB软件来说也是痛苦的 你觉得怎么样?通过使用一个

在我正在设计的数据库中,有一个相当中心的表,表示已经出售或正在出售的东西。它区分个人销售(如易趣)和正规公司的销售。这意味着字面上有1或2个字段并不同样适用于这两种情况。。。例如,一个字段仅在一种情况下使用,另一个字段在一种情况下是可选的,但在另一种情况下是强制性的。 如果有更多的特殊性,最好先有一个核心表,然后有两个表,其中包含与特定案例相关的字段。但是在这里,创建两个表只是为了包含一个字段加上对核心表的引用,这在美学上是不好的,对查询设计器和DB软件来说也是痛苦的


你觉得怎么样?通过使用一个约束较弱的表来稍微改变规则可以吗?这意味着数据库不能100%防止添加不一致的数据(以非常有限的方式)-还是我要把它吸起来,创建一个看起来很傻的单字段表?

我认为选择这些字段不会伤害到你,而是我会选择的。请记住,随着数据库的发展,您可能需要决定重构为两个单独的表(如果需要更多字段)

如果有两个不同的实体,“个人销售”和“公司销售”,那么,也许您应该有两个表来表示这些实体?

您所描述的是一个用于公共列的表和用于特定子类型列的依赖表。这是一件非常好的事情

@Scott Ferguson所描述的内容(两种销售类型的两个不同表格)被称为。根据您的需要,它也可以是一个很好的解决方案,但更多情况下,它只会使跨两个子类型编写查询变得更加困难

如果您只需要一个或两个只适用于给定子类型的列,那么我同意创建依赖表似乎有些过分。请记住,大多数品牌的SQL数据库都支持约束或触发器,因此可以在元数据中设计数据完整性规则

CREATE TABLE Sales (
 sale_id SERIAL,
 is_business INT NOT NULL, -- 1 for corporate, 0 for personal
 sku VARCHAR(20),          -- only for corporate
 paypal_id VARCHAR(20),    -- mandatory but only for personal
 CONSTRAINT CHECK (is_business = 0 AND paypal_id IS NOT NULL)
);

新闻快讯:DB无法阻止100%的损坏数据,无论您以何种方式剪切数据。到目前为止,您只考虑了我所称的级别1损坏(级别0损坏本质上是如果您使用十六进制编辑器在数据库上写垃圾会发生的情况)


我还没有看到一个可以防止2级损坏的数据库(语法正确的记录,但作为一个整体来看,意味着一些反常的东西)。

有一些人坚持不允许使用不适用的字段,但我认为这是有人写在书中的规则之一,现在我们都应该毫不怀疑地遵循它。在您描述的案例中,单个表听起来像是简单、智能的解决方案

我当然不会创建两个表。然后所有公共字段都将被复制,所有查询都必须联接或联合两个表。所以真正的问题是,一张桌子或三张桌子。但你似乎意识到了这一点

您没有澄清其他字段是什么。如果一个字段的存在或不存在意味着记录类型,那么我有时会将该事实用作记录类型指示符,而不是创建冗余类型。比如,如果“个人销售”和“商业销售”之间的唯一区别是商业销售中有一个公司的外键,那么您可以简单地声明,您将商业销售定义为一个公司的销售,并且不可能有歧义。但如果情况变得更加复杂,这可能是一个陷阱:我见过一些应用程序说,如果a为null,b=cd/7=那么它是记录类型a,否则b为null等等。如果你不能在一个字段上进行一次测试,就把它忘了,放在一个记录类型字段中

您始终可以强制代码或约束的一致性


我更担心冗余数据会造成一致性问题,而不是不适用的字段。冗余数据会产生各种各样的问题。数据不适用于记录类型?在最坏的情况下,忽略它。如果这是一个“个人销售”,而不知何故一家公司被填满了,忽略它,或者一眼就把它抹掉。问题已解决。

将所有字段保留在一个表中的
PRO
方法是去掉
JOIN
,这样可以加快查询速度

与之相反的是,您的表变大了,这使得查询速度变慢

哪一个对您的影响更大,完全取决于您的数据分布以及您最常发出的查询

一般来说,拆分更适合于
OLTP
系统,连接更适合于数据分析(倾向于扫描表)

让我们想象一下
2
场景:

  • 分割字段。共有
    1000000
    行,平均行大小为
    20
    字节,拆分字段每
    50
    行填充一次(即拆分表中的
    20000
    记录)

    我们希望这样查询:

    SELECT  SUM(mainfield + COALESCE(splitfield, 0))
    FROM    maintable
    LEFT JOIN
            splittable
    ON      splitid = mainid
    
    这将需要扫描
    20000000
    字节和嵌套循环(或哈希查找)以查找
    10000
    记录

    每个哈希查找大致相当于扫描
    10
    行,因此总时间将相当于扫描
    20000000+10*20000*20=24000000
    字节

  • 连接字段。共有
    1000000
    行,平均行大小为
    24
    字节,因此查询将扫描
    24000000
    字节

  • 正如你所看到的,泰晤士报势均力敌


    但是,如果其中一个参数发生变化(字段填充的频率更高或更少,行大小更大或更小,等等),则一个或另一个解决方案将变得更好。

    我肯定遗漏了什么;你不能有一个
    sale\u type
    字段,它接受“e-bay”或“live”或“swap-meet”之类的内容吗?你说的“DB不能10”是什么意思