0

このように設計されたデータベースが問題ないかどうかを確認する必要があります。そうでなければ、私はここで何か間違ったことをしています。
私は次の表を持っています:

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

そして、ある種の「ニュースフィード」のように使用するテーブルが1つあります。テーブルA、B、CIに何かを追加すると、このテーブルにも行が追加されます。

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

FeedIDPK自動増分
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')
;

フィード A からのものであることがわかっているデータを選択したい場合に何が起こるか見てください。このクエリでは、 (および共通の列)FeedTypeに属する列名のみが指定されていることに注意してください。Feed_A

select
      FeedID
    , Common_Column
    , A_Specific_Column
from vFeed;

ここに画像の説明を入力

実行計画にはFeedFeed_Aテーブルのみが表示され、クエリ オプティマイザーはテーブル_Bと を除外したことに注意してください_C。その2つに触れる必要はありません。

つまり、クエリで特定の列のみを使用するだけで特定のフィード データを要求し、オプティマイザーに他のすべてを整理させることができCASE ... WHEN ..ます。例のアクロバットは必要ありません。

于 2012-05-20T17:12:31.963 に答える
0

「ニュースフィード」に表示したいすべてのデータをFeedテーブルに追加します。これは重複データですが、長い目で見ればあなたの人生をずっと楽にしてくれます。

また、ニュースフィードが歴史的に正しいままであることも保証します。つまり、3 つのテーブルのいずれかでレコードを更新すると、「古い」フィード データは新しい値で更新されずにそのまま残ります。

于 2012-05-20T17:04:43.403 に答える
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 に答える