複合キーを使用して行を識別するためのガイダンス


8

行を一意であると識別するために4つの列のセットを使用する(1つは外部キーで、他の3つはfloatデータ型である)ことは良い習慣ですか(または悪影響がありますか)?(4つのキーがリンクされた)テーブル内の一意のエントリを表すテーブルを作成しようとしています。これが攻撃の良い計画なのか、それとももっと良い方法があるのか​​、私は興味があります。

視覚的な目的で、次の表を想像してください。次の表のように編成された在庫アイテムがあります:([K]は主キーの記号、線は関係です)

    Sheet_Class        Sheet_Type         Sheet_Size
    ===========        ==========         ==========
[K] Sheet_Class-.  [K] Sheet_Type--.  [K] Sheet_Size
                 '---- Sheet_Class  '---- Sheet_Type
                                          Length
                                          Width
                                          Thickness

データは次のように表示される場合がありますが、簡潔にするために、リンクされた列を持ち込むことは除外しました。

 Sheet_Class    Sheet_Type    Sheet_Size                        (Tables)
[Sheet_Class]  [Sheet_Type]  [Length], [Width], [Thickness]     (Column Values)
=============  ============  ==============================

Aluminum
               5052-H32
                             48, 96, 0.032
                             48, 96, 0.040
                             48, 96, 0.063

               6061-T6
                             60, 120,0.032
                             60, 120,0.040
                             60, 120,0.063

Steel
               1018-CRS
                             48, 96, 0.018
                             48, 96, 0.023
                             48, 96, 0.031

現状のまま(および上記の「スキーマ」で示したように)、Sheet_Sizeテーブルのエントリには単純な(自動インクリメント)整数の主キーを使用します。ただし、代わりにSheet_TypeLengthWidth、およびThicknessの各列の組み合わせを使用する方が良いかどうか知りたいですか?Sheet_Sizeの各エントリはこれらすべての固有の品質を共有する必要があり、自動インクリメントフィールドはこれを十分に実証しないとしたら、これは最適なルートですか?

状況を十分に説明していない場合はお知らせください。他のロジックの目的のために、インベントリされた資料のこれらの部分(クラスvsタイプvs実際の在庫サイズ)を分割する必要があることに気づきましたが、他の種類のフィードバックを求めています。

どんなガイダンスもいただければ幸いです。

更新(2011年8月12日)

回答が投稿された後、私はマークの回答X-Zeroの回答を組み合わせることにしました。長さ、幅、厚さの列に一意の制約を設定することをお勧めしますが、マテリアルサイズを一意の行に分割し、それらを関係にリンクするというアイデアも気に入っています。

残念ながら、私は両方の答えを受け入れることはできません。そのため、問題をより批判的に見て(スキーマの調整を)提供するために(私が感じていること)を取るためにX-Zerosを受け入れます。

皆様、お返事ありがとうございます。

回答:


6

これについて考えた後、テーブル構造を少しだけ修正します。
まず、シートサイズテーブルを修正します。

Sheet_size
===========
Id
Length
Width
Thickness

次に、シートサイズ/タイプの関係テーブルを作成します。

Sheet_size_type
================
Sheet_Type_Id
Sheet_Size_Id

次に、次の制約を作成します。

  1. の主キー(およびインデックス)はSheet_sizeid列である必要があります
  2. のディメンションに強制される何らかの一意のキー(およびインデックス)があるはずSheet_sizeです。2つの次元のシート(48、96、.5)と(96、48、.5)が等しい(つまり、次元の方向が重要か)と考えてください。この種の問題は、主キーの一部として列を使用する場合は適用が難しいかもしれませんが、制約やストアドプロシージャを使用するとより管理しやすくなります。
  3. の主キー(およびインデックス)はSheet_size_type、カーディナリティが低い方から始めて、両方の外部キーを使用する必要があります(おそらくsheet_type、例では)。別の方向に追加のインデックスが必要な場合がありますが、それは必ずしも必要ではありません。

このリビジョンはデータベーススペースを節約し(同じサイズを使用するシートタイプの数の比率として)、オーバーヘッドにあまり影響を与えません。


floatデータ型を使用している場合、不正確さが予期せずトリップする可能性があるため、等価性/一意性に関する他の潜在的な懸念があります。固定小数点型が、特定の精度でより適切かどうかを検討する必要があります。


長さと幅を1つ(可能な場合は2つ)の小数点に制限することを計画していました。厚さは(最大で)3つまで拡張されます。それを超えて、私たちは有限になりすぎています(とにかく、株式自体は記述された数字に決して入りません)。それはさておき、私はシートサイズを分割するという考えが好きですが、私が直面している問題は、関係する他の列(除外したもの)です。(さらに部屋が必要です。次の投稿を参照してください)
ブラッドクリスティ

これは在庫のリストであるため、密度やコスト/ポンドなどのその他の情報を含める必要があります(タイプ(および厚さも)に大きく基づいています。たとえば、 "Steel" / "1018"は$ 0.55 / lbになる可能性があります。 0.018〜0.125インチの厚さですが、厚さが0.125インチを超えると$ 0.65 / lbになります(これは、48 "x96" x0.250 "のシートサイズ1018と5052-H32の間でも異なります)。例では、 48 "x96" x0.125 "のエントリは1つしかありません(ただし、関係テーブルにこれらの追加のメトリックを含めることができると思います)
ブラッドクリスティー

少数の小数点以下の桁数だけが必要な場合は、固定精度を使用します。はい、ここで(この場合)そのような情報を入力します(たとえば、コストはシートのタイプとサイズに依存します)。ただし、参照できる追加のテーブルを生成することもできます。また、人々が予期しない方法でデータをクエリしようとしないように、カスタムデータ型(密度など)の作成を検討することもできます。
時計じかけのミューズ

6

以下のように見える自然サロゲートキーの決定、意見の範囲れていると考えると実用的学術的な教義を境に、。RDBMSによっては、SQL Serverでのクラスター化されたキーの選択など、パフォーマンスに大きな影響を与える可能性のある物理モデルに関する考慮事項があります。

個人的には、狭い単一の属性候補キーがある場合、それを利用したくなります。ワイドキーまたは複合キー、あるいはその両方。デフォルトでは、モデルにサロゲートを追加しています。あなたのケースでは、プライマリクラスター化キーとしてのSheet_SizeのID列と、タイプ/長さ/幅/厚さに対する一意の制約に投票します。


しかし、行に「任意の」キーが与えられたとすると、uniqueはどのようにして(組み合わせたときに)列が重複した値を持たないように強制しますか?一意の属性がキーに関連していることは私の理解です。あなたは言っSheet_Size INT PRIMARY KEYているLength UNIQUE、そしてWidth UNIQUEThickness UNIQUE?それでも(挿入インターフェイスにロジックを適用せずに)テーブル内の重複を防ぐ方法がわかりません。(たぶん、私は何かが足りないのでしょうか?)
ブラッドクリスティー

3つの列に対する一意の制約:ALTER TABLE dbo.Sheet_Size ADD CONSTRAINT UC_LengthWidthThickness UNIQUE([Length]、[Width]、[Thickness])
Mark Storey-Smith

フィードバックありがとうございます。列に対する一意の制約が優れた解決策になることに同意しますが、サイズを新しいテーブルに分割する(新しいテーブルにリンクされている)X-Zeroの推奨事項も気に入っています。したがって、アイデアを組み合わせるために、密度とコスト/ lbの情報を削除して関係テーブルに配置しながら、「切り捨て」サイズテーブルに一意の制約を適用します。
ブラッドクリスティ

4

前の質問からのこの回答に少しリダイレクトします。

引用:「その主キーの設計方法については、2つの考え方があります。

  • PKをGUIDまたは自動インクリメントINTのように、通常は自己生成された個別の列として作成するもの(あなたの場合は個別のuniqueidentifier列)。
  • PKをテーブルの内部の列(または列のセット)として作成するもの(この場合、ユーザーを一意にするものは、ユーザー名、電子メール、またはSSNになります)は、レコードを一意に識別します。

どちらに忠実であっても、それは好みの問題です。」

選択したソリューションの副作用は次のとおりです。

  • どこでも複合キーを使用すると、次のようになります。

    • 関連するすべてのテーブルのストレージを増やします。
    • 頻繁に使用されるFKのインデックスの増加/複雑化。
    • すべての結合ステートメントの記述を少し複雑にする
    • 作る氏はジョー・セルコの(天然または人工のキーに関する彼の意見についての言及を見つけることができます:-)幸せをここここ、とほとんどどこでも彼は問題について尋ねています)
  • 生成されたキーを使用すると、次のようになります。

    • 前の3つのステップを簡略化する
    • ID PKでテーブルを複製する状況を複雑にします(ここここ、またはここの参照

私は個人的に生成されたINT IDENTITYキーを支持していますが、あなたに合ったもので結構です。


2

複合キーは完全に理にかなっています。そのキーを実装することで、ビジネス属性を複製できなくなります。同じデータを複数回記録すると、あいまいさ、望ましくない依存関係が発生し、ユーザーエラーや誤ったデータが発生する可能性が高くなるため、これは良いことです。

自動インクリメントキーだけでは、ビジネスデータの整合性は保護されません。自動インクリメントキーが特定の目的を果たさない場合(たとえば、別のテーブルの外部キー参照のターゲットとして)、安全に削除できます。


...外部キーとして自動インクリメントを削除する場合を除き、すべてのディメンション列を外部キーの一部として使用する必要があります(つまり、4つの列すべて(タイプを含める場合))。私が外部キーとして欲しいものではありません、ピリオド-単一列のみ、お願いします。ディメンション(およびテーブルのデザインに応じてタイプ)に一意のキー(および/またはチェック制約)を配置することは良い考えであることに同意します。
時計じかけのミューズ

@ X-Zero、私は2番目のパラグラフで外部キー参照について指摘しました。私が読んだときの問題は、複合キーを実装するかどうかではなく、自動インクリメントを持つかどうかです。
nvogel 2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.