0

SQLServerテーブルがあります。

+----+-------------+-------------------+
| ID | CompanyID   | CompanyCode       |
+----+-------------+-------------------+
| 1  | 1           | AAAA-123          |
| 2  | 2           | BBBB-111          |
| 3  | 1           | AAAA-123          |
| 4  | 3           | CCCC-999          |
| 5  | 3           | CCCC-999          |
| 6  | 1           | AAAA-123          |
+----+-------------+-------------------+

フィールドはIDPKです。

CompanyIDandCompanyCodeフィールドは一意の会社を指定します。これにより、aは常にCompanyID同じCompanyCode(およびその逆)になり、2つの会社が同じCompanyIDおよび/またはを持つことはありませんCompanyCode

が一致する既存の場所とCompanyCode一致しない場合に、レコードをテーブルに追加できないようにするルールをテーブルに作成したいと思います。CompanyCodeCompanyID

以下は、私がテーブルで発生することを許可できないことの例です。

+----+-------------+-------------------+
| ID | CompanyID   | CompanyCode       |
+----+-------------+-------------------+
| 1  | 1           | AAAA-123          |
| 2  | 1           | BBBB-111          |<<<< This record should not be allowed
| 3  | 1           | AAAA-123          |
| 4  | 3           | CCCC-999          |
| 5  | 3           | CCCC-999          |
| 6  | 1           | AAAA-123          |
+----+-------------+-------------------+

が付いているレコードに注意してください。は、が付いている既存のレコードと一致ID=2CompanyCode BBBB-111ませんCompanyCode of AAAA-123

このルールを何らかの形でテーブルに存在させたい-つまり、このルールをクエリやストアドプロシージャが管理する必要のあるビジネスルールにしたくない。

テーブルに既存および/または存在する場合にのみ、重複レコード(onCompanyIDおよび)を強制したいと言うことができると思います。CompanyCodeCompanyIDCompanyCode

これはテーブルデザインレベルで行うことができますか?または、スクリプトでこれを管理する必要がありますか?

アップデート

これは私のOPにはあまり関係ありませんが、受け取ったフィードバックから、CompanyID/CompanyCodeテーブルの設計について少し背景を説明する必要があると思います。

まず、これは私の質問を説明するための単なる模擬テーブルのデザインです。私の実際のテーブルは企業とは何の関係もありません。

次に、私の実際のテーブルは、Service1がを作成しDeviceID、Service2がマイクロデバイスに存在するを収集する2つのWebサービスの仲介者です。SerialNumberまた、私の実際のテーブルには、この仲介サーバーが処理しなければならない他の多くの列が含まれています。

この仲介サービスの奇妙な点の1つは、私が話しているテーブルでは、DeviceIDとSerialNumberの両方にNULLを許可する必要があることです。これはすべて、どのサービスが最初にレコードを送信したかによって異なります。話しすぎて元の質問のトピックから外れましたが、正規化を破ることに関して多くの問題が発生していたため、テーブルの例を明確にする必要があると思いました。

4

5 に答える 5

4
 CREATE UNIQUE INDEX idx_name ON TableName(CompanyID, CompanyCode)

(テーブルの名前がTableNameであると仮定します)。

ただし、この設計はデータベースの正規化の原則に違反していることに注意してください。適切に正規化されたデータベースには、CompanyIDフィールドとCompanyNameフィールドのみを持つ個別のテーブルがあります。次に、例のテーブルを変更して、CompanyIDフィールドのみを含めます。CompanyCodeは、必要に応じて(VIEWを使用して)「ルックアップ」されます。

この設計には次の利点があります。

  1. 同じ会社IDで異な​​る名前を付けることは文字通り不可能になります。

  2. 会社がコードを変更した場合、エラーがなく高速な単一のテーブルの1つのレコードを更新するだけで済みます。

  3. ストレージを節約できます。

コードを取得するには、Companyテーブルに参加する必要があるという小さな欠点があります。必ずしも実際の欠点ではないリレーショナルデータベース(正規化されたデータの結合はリレーショナルデータベースの目的です)ですが、CompanyIDを削除し、コードを企業の主キーとして使用することで、それを排除することもできます。コードが不変である場合にのみこれを検討します(特定の会社では時間の経過とともに変更されません)。

于 2012-04-04T12:46:48.030 に答える
2

CompanyIDとCompanyCodeをテーブルに格納しないことをお勧めします。代わりに、CompanyIdごとに1行を格納し、それに対応するコードを含む別のテーブルが必要です。次に、外部キーを設定して、このテーブルのCompanyIdが他のテーブルに存在することを確認できます。

于 2012-04-04T12:48:12.333 に答える
2

これを強制するルールを作成することについてはわかりませんが、同じものに2つの別個の外部キーを使用しています(これは常に一致します)...このテーブルに会社コードを含めない方がよいでしょう。データが必要なときにすべてを別のテーブルに結合するか、他の方法で再設計します

于 2012-04-04T12:49:36.837 に答える
0

3番目の正規形に違反しています。非キーは別の非キーに依存しています。CompanyCodeはCompanyIDに依存しています。他の人が述べているように、解決策は、CompanyIDがPKであるCompanyID、CompanyCodeテーブルを作成することです。テーブルからCompanyCodeを削除し、新しいテーブルを指すComanyIDにFK関係を作成します。 http://www.phlonx.com/resources/nf3/ http://en.wikipedia.org/wiki/Third_normal_form

于 2012-04-04T13:50:06.793 に答える
0

さて、これは最も美しいコードではありませんが、制約を強制するものだと思います。秘訣は、2つの一意のインデックスが定義されたインデックス付きビューを作成することです。

create table dbo.ABC (
    Col1 int not null,
    Col2 int not null
)
go
create view dbo.ABC_Col1_Col2_dep
with schemabinding
as
    select Col1,Col2,COUNT_BIG(*) as Cnt
    from
        dbo.ABC
    group by
        Col1,Col2
go
create unique clustered index IX_Col1_UniqueCol2 on dbo.ABC_Col1_Col2_dep (Col1)
go
create unique nonclustered index IX_Col2_UniqueCol1 on dbo.ABC_Col1_Col2_dep (Col2)
go

次に、いくつかの初期データを挿入します。

insert into dbo.ABC (Col1,Col2)
select 1,3 union all
select 2,19 union all
select 3,12

Col1Col2:にまったく同じ値を持つ別の行を追加できます。

insert into dbo.ABC (Col1,Col2)
select 1,3

Col2ただし、別の値に使用されている値を選択した場合Col1、またはその逆の場合、エラーが発生します。

insert into dbo.ABC (Col1,Col2)
select 2,3
go
insert into dbo.ABC (Col1,Col2)
select 1,5

ここでの秘訣は、このクエリを観察することでした。

    select Col1,Col2,COUNT_BIG(*) as Cnt
    from
        dbo.ABC
    group by
        Col1,Col2

Col1強制しようとしている制約が破られていない場合、特定の値に対して1つの行のみ、特定の値を持つ1つの行のみがCol2含まれますが、一致しない行がベーステーブルに挿入されるとすぐに、このクエリは複数の行を返します。

于 2012-04-04T14:42:02.063 に答える