4

現在、レガシーデータベースの設計を改善しようとしていますが、次のような状況があります

現在、LeadSource を格納するテーブル SalesLead があります。

Create Table SalesLead(
    ....
    LeadSource varchar(20)
    ....
)

リード ソースはテーブルに保存されているので便利です。

Create Table LeadSource (
    LeadSourceId int,   /*the PK*/
    LeadSource varchar(20)
)

したがって、一方から他方への外部キーを作成し、正規化されていない列を削除したいだけです。

すべての標準的なもの、私は願っています。

これが私の問題です。私は書く代わりにその問題から逃れることができないようです

 SELECT * FROM SalesLead Where LeadSource = 'foo'

これは完全に明白であり、私は今書かなければなりません

SELECT * FROM SalesLead where FK_LeadSourceID = 1

また

SELECT * FROM SalesLead 
INNER JOIN LeadSource ON SalesLead.FK_LeadSourceID = LeadSource.LeadSourceId 
where LeadSource.LeadSource = "foo"

LeadSource フィールドの内容を変更すると、これが壊れます。

私のアプリケーションでは、SalesLead の LeadSource の値を変更したいときはいつでも、1 から 2 に更新したくありません (たとえば)。開発者にこれらのマジック ナンバーを覚えさせたくないからです。ID は任意であり、そのままにしておく必要があります。

アプリのコードでそれらへの依存を削除または無効にするにはどうすればよいですか?

私のソリューションがサポートしなければならない言語を編集する

  • .NET 2.0 + 3 (価値のある asp.net、vb.net、および c#)
  • vba (アクセス)
  • デシベル (MSSQL 2000)

2.0編集結合は問題ありませんが、リクエストに応じて「foo」が「foobar」に変更される可能性があり、クエリを実行したくありません。

4

7 に答える 7

3

テーブルを非正規化する場合は、FK または ID を使用する代わりに、LeadSource (Varchar) 列を SalesLead テーブルに追加するだけです。

一方、言語が ENUM 構造をサポートしている場合、「マジック ナンバー」は列挙型に安全に格納する必要があるため、次のことが可能です。

SELECT * FROM SALESLEAD WHERE LeadSouce = (int) EnmLeadSource.Foo; //pseudocode

そして、あなたのコードには

public enum EnmLeadSource 
{
   Foo = 1,
   Bar = 2
}

過度の正規化が原因で問題が修正される以上の問題が発生する場合は、正規化を削除してもかまいません。ただし、(マジック ナンバーではなく) VARCHAR フィールドを使用する場合は一貫性を維持する必要があり、後で複数の言語や文化が必要な場合はローカライズが難しくなる可能性があることに注意してください。

正規化後の最善のアプローチは、Enum 構造を使用することです。コードをクリーンに保ち、メソッドや関数間でいつでも列挙型を渡すことができます。(ここでは.NETを想定していますが、他の言語でも同様です)

更新: .NET を使用しているため、コードを使用してクエリを作成している場合、DB バックエンドは「無関係」です。この関数を想像してください:

public void GiveMeSalesLeadGiven( EnmLeadSource thisLeadSource )
{
  // Construct your string using the value of thisLeadSource 
}

テーブルには、LeadSource (INT) 列があります。しかし、それが 1、2、または N であることは問題ではありません。後で foo を foobar に変更する必要がある場合は、次のことを意味する可能性があります。

1) 「数字の 1」はすべて「数字の 2」でなければなりません。テーブルを更新する必要があります。2) または、Foo を 2 番、Bar を 1 番にする必要があります。Enum を変更するだけです (ただし、テーブルの値が一貫していることを確認してください)。

Enum は、適切に使用すれば非常に便利な構造です。

お役に立てれば。

于 2008-09-17T09:50:57.753 に答える
2

LeadSourceテーブルに人工キーを使用しないことを検討しましたか?次にLeadSource、のFKとして使用できるようになりSalesLeadます。これにより、正規の値のセット(の行)を使用する利点を維持しながら、クエリが簡素化されますLeadSource

于 2008-09-17T12:34:54.783 に答える
1

更新可能なビューを検討しましたか? データベース サーバーとデータベース設計の整合性に応じて、値が変更されたときに構成テーブルを更新するビューを作成できます。

于 2008-09-17T09:47:57.883 に答える
0

通常のアプリケーションでは、ユーザーにリードソースのリスト(LeadSourceテーブルのクエリによって返される)が表示され、後続のSalesLeadクエリはユーザーの選択に基づいてアプリケーションによって動的に作成されます。

アプリケーションには、特定のクエリを作成する必要のある「よく知られた」リードソースがいくつかあるようです。この場合は、アプリケーションのクエリの基礎として使用できる不変の「名前」を含む3番目の(一意の)フィールドをLeadSourceテーブルに追加します。

これにより、魔法の負担がDBで生成された魔法の番号(インストールごとに異なる場合があります)からシステムで定義された魔法の名前(設計によって固定されている)にシフトします。

于 2008-09-17T10:01:22.173 に答える
0

ここには誤った二分法があります。

SELECT * FROM SalesLead 
INNER JOIN LeadSource ON SalesLead.FK_LeadSourceID = LeadSource.LeadSourceId 
where LeadSource.LeadSource = "foo"

オリジナル以上に壊れない

SELECT * FROM SalesLead Where LeadSource = 'foo'

foo変わるときfoobar。また、パラメータ化されたクエリを使用している場合 (実際に使用する必要があります)、 を に変更するときに何も変更する必要はありませfoofoobar

于 2008-09-17T11:29:35.800 に答える
0

新しいリレーション/テーブルを導入して「設計を改善」する場合、確かに別のエンティティが必要になります。もしそうなら、それらのセマンティクスに対処する必要があります。

前のソリューションでは、適切な SalesLead 行で LeadSource 名を任意の名前に更新するだけで済みました。新しい構造で名前を更新する場合は、すべての SalesLead 行に対して行います。

これらの異なるセマンティクスに対処する方法はありません。あなたはそうしなければなりません。テーブルのクエリを簡単にするために、すでに提案されているようにビューを使用することもできますが、主にレポート目的または下位互換性のために更新可能ではないことを期待しています。 .

結合が気に入らない場合は、SELECT * FROM SalesLead where LeadSourceId IN (SELECT Id FROM LeadSource WHERE LeadSource = 'foo') を試してください。

于 2008-09-17T09:58:49.560 に答える
0

結合の背後にあるあなたの問題は本当にわかりません。

当然、FK_LeadSourceID で直接尋ねるのは間違っていますが、ID の変更を完全にマスクするので、JOIN を使用するのが正しい方法のようです。たとえば、ある日「foo」が 3 になった場合 (そして外部キー フィールドを更新した場合)、最後に表示したクエリはまったく同じように機能します。

アプリケーションの現在のクエリを変更せずにスキーマを変更したい場合は、この結合を含むビューが最適です。

または、結合構文が直感的ではないのではないかと心配している場合は、常にサブセレクトがあります...

SELECT * FROM SalesLead where FK_LeadSourceID = 
         (SELECT LeadSourceID from LeadSource WHERE LeadSource = 'foo')

ただし、LeadSource.LeadSource にインデックスを保持することを忘れないでください - 少なくともテーブルに多くのインデックスが格納されている場合。

于 2008-09-17T09:51:17.890 に答える