我只是需要一些确认是数据库设计像这样好或不。如果不是,我在这里做错了。
我有以下表格:
TableA{TableAID,...}
TableB{TableBID,...}
TableC{TableCID,...}
etc.
我有一张桌子,我喜欢某种'新闻Feed'。当我在任何表A,B,C中添加内容时,我还在此表中添加行。
Feed{FeedID, TypeID, ReferenceID,...}
FeedID
是PK自动增量
TypeID
是引用类型表的编号,根据此ID我知道该表中的行是表A,B,C。
ReferenceId
是表A,B,C中项目的ID
A,B,C表都有不同的字段
现在,当我想获取Feed数据时,我还需要从每个表中获取一些数据,以便在应用程序中使用它。在我的查询中,我使用了很多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,
...
答案 0 :(得分: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;
请注意,执行计划仅显示Feed
和Feed_A
个表,查询优化器消除了表_B
和_C
;没必要碰那两个。
换句话说,您只需在查询中使用特定列就可以请求特定的Feed数据,并让优化程序对其他所有内容进行排序 - 您的示例中不需要CASE ... WHEN ..
杂技。
答案 1 :(得分: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
);
您可以使用复杂的检查约束或触发器强制在给定类型的相关列中存在/不存在数据。但是,如果Feed可以轻松更改类型,那么您必须拥有相当复杂的逻辑(就像在当前模型中一样)。
答案 2 :(得分:0)
将您要显示的所有数据添加到Feed
表格中的“新闻Feed”中。它是重复数据,但从长远来看,它将使您的生活更轻松。
它还可确保您的新闻源保持历史正确。这意味着当我更新三个表之一中的记录时,“旧”Feed数据保持不变,而不是使用新值更新。