0

我只需要一些确认是这样设计的数据库是否可以。如果不是我在这里做错了什么。
我有以下表格:

TableA{TableAID,...}
TableB{TableBID,...}
TableC{TableCID,...}
etc.

我有一张桌子,我用它就像某种“新闻提要”。当我在任何表 A、B、CI 中添加内容时,也会在此表中添加行。

Feed{FeedID, TypeID, ReferenceID,...}

FeedID是 PK 自动增量
TypeID是引用类型表的数字,并且基于此 ID,我知道此表中的行来自表 A、B、C。
ReferenceId是表 A、B、C 中项目的 ID。
A、B、C 表都有不同的字段。
现在,当我想获取提要数据时,我还需要从每个表中获取一些数据以在应用程序中使用它。在我的查询中,我使用了很多SELECT CASE CLAUSE类似的东西:

我首先加入查询中的所有表(A,B,C)

...
CASE Feed.TypeId              
               WHEN 1 THEN tableA.someData
                           WHEN 2 THEN tableB.someData
                           WHEN 3 THEN tableC.someData
          END AS Data,
...

在此处输入图像描述

4

3 回答 3

1

如果不考虑此特定目的的适用性,您的超类型 - 子类型模型是“颠倒的”。

在此处输入图像描述

所以 DDL 看起来像

CREATE TABLE Feed ( 
      FeedID               integer  IDENTITY(1,1) not null
    , FeedType             char(1)  not null
  --  Common_Columns_Here
    , Common_Column        varchar(20)
);
ALTER TABLE Feed ADD CONSTRAINT pk_Feed PRIMARY KEY (FeedID) ;


CREATE TABLE Feed_A ( 
      FeedID               integer  not null
  --  A_Specific_Columns_Here
    , A_Specific_Column    varchar(20)
);
ALTER TABLE Feed_A ADD
  CONSTRAINT  pk_Feed_A PRIMARY KEY (FeedID)
, CONSTRAINT fk1_Feed_A FOREIGN KEY (FeedID) REFERENCES Feed(FeedID) ;


CREATE TABLE Feed_B (
      FeedID               integer  not null
  --  B_Specific_Columns_Here
    , B_Specific_Column    varchar(20)
);
ALTER TABLE Feed_B ADD 
  CONSTRAINT  pk_Feed_B PRIMARY KEY (FeedID)
, CONSTRAINT fk1_Feed_B FOREIGN KEY (FeedID) REFERENCES Feed(FeedID) ;


CREATE TABLE Feed_C ( 
      FeedID               integer  not null
  --  C_Specific_Columns_Here
    , C_Specific_Column    varchar(20)
);
ALTER TABLE Feed_C ADD 
  CONSTRAINT  pk_Feed_C PRIMARY KEY (FeedID)
, CONSTRAINT fk1_Feed_C FOREIGN KEY (FeedID) REFERENCES Feed(FeedID) ;

现在,为了从这个结构中读取,首先创建一个视图

create view vFeed as
select
      f.FeedID
    , FeedType
    , Common_Column
    , A_Specific_Column
    , B_Specific_Column
    , C_Specific_Column
from      Feed   as f
left join Feed_A as a on (a.FeedID = f.FeedID and f.FeedType = 'A')
left join Feed_B as b on (b.FeedID = f.FeedID and f.FeedType = 'B')
left join Feed_C as c on (c.FeedID = f.FeedID and f.FeedType = 'C')
;

看看当我想选择我知道来自 feed A 的数据时会发生什么。请注意,FeedType此查询中未指定,仅指定属于Feed_A(和公共列)的列名。

select
      FeedID
    , Common_Column
    , A_Specific_Column
from vFeed;

在此处输入图像描述

请注意,执行计划仅显示FeedFeed_A表,查询优化器消除了表_B_C; 没必要碰那两个。

换句话说,您可以通过仅使用查询中的特定列来请求特定的提要数据,并让优化器对其他所有内容进行排序——不需要CASE ... WHEN ..您的示例中的杂技。

于 2012-05-20T17:12:31.963 回答
0

正如我在评论中所建议的(以及@Andomar 的智慧),我认为这样的事情会更好:

CREATE TABLE dbo.FeedTypes
(
  FeedTypeID INT IDENTITY(1,1) PRIMARY KEY,
  SomedataA INT,
  SomedataB VARCHAR(32),
  SomedataC DATETIME
  --, ... other columns
);

CREATE TABLE dbo.Feeds
(
  FeedID INT IDENTITY(1,1) PRIMARY KEY,
  FeedTypeID INT NOT NULL FOREIGN KEY
    REFERENCES dbo.FeedTypes(FeedTypeID)
  --, ... other columns
);

您可以使用复杂的检查约束或触发器强制在给定类型的相关列中存在/不存在数据。但是,如果提要可以轻松更改类型,则必须具有相当复杂的逻辑(就像在当前模型中那样)。

于 2012-05-20T16:32:09.117 回答
0

Feed在表格的“新闻提要”中添加您希望显示的所有数据。这是重复的数据,但从长远来看,它会让你的生活更轻松。

它还确保您的新闻源保持历史正确性。这意味着当我更新三个表之一中的记录时,“旧”提要数据保持不变,而不是使用新值进行更新。

于 2012-05-20T17:04:43.403 回答