トップ回答者
正規化について

質問
-
ご教授お願いいたします。
さて、このカテゴリーで質問していいのかわからないため
データーベースということでここに質問します。内容は、テーブルの正規化についてです。
テーブルを作成し
リーレーションで繋げてみたら
不明なリレーションができました。
原因は分かったのですが、その原因で
テーブルを編集していいものかどうかわかりませんでした。そのテーブル構成は
担当者マスタのテーブル
フィールドは、ID,コード,担当者名,・・・となり
得意先マスタのテーブル
フィールドは、ID,コード,得意先名,担当営業コード,担当製造者コード,・・・で作成しました。問題となった個所は
得意先マスタの担当営業コードと担当製造者コードとなります。
この各コードは、担当者マスタのコードとリレーションします。原因から、直接担当者マスタでリレーションを行わず
営業担当者マスタテーブルと製造担当者マスタテーブルを中間に配置して
その下に担当者マスタをリレーションしなくてはいけないと
とある人から教えを受けました。以上のことより、テーブルの正規化について正しいテーブル構成を
ご回答頂きたいです。
恥ずかしながら、独学で正規化を学んだためどれが正しいのかわかりません。以上
回答
-
(違っていたら誰かつっこんでください)
Table-A と Table-B の間に 1:N の関係がある場合、これを Table-A の複数の列を使って表現するのは、第1正規形に反しています。
これは、例えば「得意先マスタ」に「保守担当者」を追加するようなことがあった場合に、「得意先」と「担当者」のテーブル間のリレーションに変更がはいってしまうことが問題だとされています。プログラム的に言えば、『得意先に関連する担当者一覧』を取得する『結合条件』にたいして変更が入ってしまうということです。
> 営業担当者マスタテーブルと製造担当者マスタテーブルを中間に
このあたりの使い方にもよるんですが、例えば、
CREATE TABLE 担当者 ( ID INT, NAME NVARCHAR(200), PRIMARY KEY (ID) ); CREATE TABLE 得意先 ( ID INT, NAME NVARCHAR(200), PRIMARY KEY (ID) ); CREATE TABLE 得意先担当者 ( 得意先ID INT, 担当作業CD INT, 担当者ID INT, PRIMARY KEY (得意先ID, 担当作業CD) );
こんな構造であれば、保守作業担当者を保持するように変更した場合、担当作業CDを「営業担当」「製造担当」の2つから「保守担当」を追加するだけで対応できます。また、担当者を取得する処理において結合条件には担当作業CDは関係ないので影響がないですし、個別の「営業担当者」や「製造担当者」を取得している処理についても、コードが変化しないかぎりは影響がないはずです。※ これは営業担当者マスタと製造担当者マスタに分割しない場合で、分割する場合にも同じことが言えるはずです。
-
中間テーブルを設ける理由でよくあるのは、1対1ではなく1対多の場合のケースです。この例では担当営業や担当製造者が一つの得意先に複数存在するケースです。また、リレーションを張るなら絶対に変わらない一意のキーがベストです。担当者マスタにIDという主キーらしきものが見えますので、せっかくであれば以下のようにすれば良いと思います。
担当者マスタ: 担当者ID, ・・・
得意先マスタ: 得意先マスタID, コード, 得意先名, ・・・
得意先担当営業: 得意先マスタID, 担当者ID
得意先担当製造者: 得意先マスタID, 担当者ID
もしくは、得意先担当営業と得意先担当製造者を一つにまとめて、得意先担当として、
得意先担当: 得意先マスタID, 担当者ID, 関係区分 #関係区分は、1:担当営業、2:担当製造者
でも良いと思います。
不明なリレーションというのはよくわからないのですが、上記のような構造で外部参照性制約を取ればそのようなことは無くなります。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
すべての返信
-
(違っていたら誰かつっこんでください)
Table-A と Table-B の間に 1:N の関係がある場合、これを Table-A の複数の列を使って表現するのは、第1正規形に反しています。
これは、例えば「得意先マスタ」に「保守担当者」を追加するようなことがあった場合に、「得意先」と「担当者」のテーブル間のリレーションに変更がはいってしまうことが問題だとされています。プログラム的に言えば、『得意先に関連する担当者一覧』を取得する『結合条件』にたいして変更が入ってしまうということです。
> 営業担当者マスタテーブルと製造担当者マスタテーブルを中間に
このあたりの使い方にもよるんですが、例えば、
CREATE TABLE 担当者 ( ID INT, NAME NVARCHAR(200), PRIMARY KEY (ID) ); CREATE TABLE 得意先 ( ID INT, NAME NVARCHAR(200), PRIMARY KEY (ID) ); CREATE TABLE 得意先担当者 ( 得意先ID INT, 担当作業CD INT, 担当者ID INT, PRIMARY KEY (得意先ID, 担当作業CD) );
こんな構造であれば、保守作業担当者を保持するように変更した場合、担当作業CDを「営業担当」「製造担当」の2つから「保守担当」を追加するだけで対応できます。また、担当者を取得する処理において結合条件には担当作業CDは関係ないので影響がないですし、個別の「営業担当者」や「製造担当者」を取得している処理についても、コードが変化しないかぎりは影響がないはずです。※ これは営業担当者マスタと製造担当者マスタに分割しない場合で、分割する場合にも同じことが言えるはずです。
-
佐佑理さんも言われてますが、いまひとつ質問の意図が掴みかねます。
> 恥ずかしながら、独学で正規化を学んだためどれが正しいのかわかりません。どのように正規化を学ばれたか気になります。
ツールの操作方法から正規化を学んだのなら、正規化を正しく理解されてない可能性が考えられます。
一度以下のような書籍をじっくり読んで勉強されてはいかがでしょうか?http://www.amazon.co.jp/dp/4798103853/
#最近 DB 関連の書籍読んでないので、どれがお勧めかわかりませんが・・・
ひらぽん http://d.hatena.ne.jp/hilapon/ -
中間テーブルを設ける理由でよくあるのは、1対1ではなく1対多の場合のケースです。この例では担当営業や担当製造者が一つの得意先に複数存在するケースです。また、リレーションを張るなら絶対に変わらない一意のキーがベストです。担当者マスタにIDという主キーらしきものが見えますので、せっかくであれば以下のようにすれば良いと思います。
担当者マスタ: 担当者ID, ・・・
得意先マスタ: 得意先マスタID, コード, 得意先名, ・・・
得意先担当営業: 得意先マスタID, 担当者ID
得意先担当製造者: 得意先マスタID, 担当者ID
もしくは、得意先担当営業と得意先担当製造者を一つにまとめて、得意先担当として、
得意先担当: 得意先マスタID, 担当者ID, 関係区分 #関係区分は、1:担当営業、2:担当製造者
でも良いと思います。
不明なリレーションというのはよくわからないのですが、上記のような構造で外部参照性制約を取ればそのようなことは無くなります。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/ -
こんにちは、zeak01 さん。
MSDN フォーラムのご利用ありがとうございます。オペレーターの山本です。
しばらく時間が経ちましたが、その後いかがでしょうか。
みなさんから参考になるアドバイスをいただいているかと思われましたので、勝手ながら私のほうで一旦回答としてマークさせていただきました。
情報くださったみなさん、ありがとうございます。
zeak01 さん、一旦回答としてマークさせていただきましたが、zeak01 さんが意図する内容と違うなどといった場合や、追加情報などある場合には、その詳細を投稿してご質問を続けてくださいね。
今後とも、MSDN フォーラムをよろしくお願いいたします。
日本マイクロソフト株式会社 フォーラム オペレーター 山本 春海