• ベストアンサー

第3正規化するかどうか

第3正規化ってどういう条件でやるものなのでしょうか? http://su10.sgu.ac.jp/~morita/Seminar/6thStudent/siohara/formalize.html 上記だと第3正規化でGenre_nameを分離していますが、 Genre_codeで定まる値が一つならGenre_codeをなくしてGenre_nameをCinemaに直接書いても大差ないように思えます。 (Genre_codeに従属している項目が複数だったらやるべきだと思いますが) 現在テーブルを作成しているのですが、 上記のようにコードをつけて分離しようと思えばできる項目が複数あり、 やるべきかやらざるべきかで悩んでおります。 基本的にやれるところはやった方がいいのでしょうか? (個人的にはテーブルが増えると管理が面倒なのでコードにするにしても、 参照するプログラム側で連想配列でも持たした方が楽かなと思っているのですが)

質問者が選んだベストアンサー

  • ベストアンサー
  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.3

 追加でもう一点。  データベースシステムを利用する、最大の動機と利点は、複数のアプリケーションで、同じデータを扱う時に、統一した方法で同じデータをアクセスできるということです。  この目標を達成するためには、データそのものがもつ性質は可能な限りデータベースだけで実現しなければなりません。データの整合性もそのひとつですし、データの制約もそうです。(例えば、数値は正の数値であるはずとか、この項目は絶対に定義されていなければならないとか、そういった類の指定です。)  従って、「(個人的にはテーブルが増えると管理が面倒なのでコードにするにしても、参照するプログラム側で連想配列でも持たした方が楽かなと思っているのですが)」という発想はやめましょう。これをやると、総てのアプリケーションが、この約束を守るための同じコードを書かなくてはならないと言うことになります。これは、最初の目標に背を向ける行為ですから。  これにより、考え方として、もう一つ追加しておきます。  データのチェックや処理ロジックにまつわる事項は、可能な限りデータベース側で実現できるように考えてください。単純な値のチェックはもちろんのこと、データの抽出や選別・集計などはSQL文で行うことを前提にすることです。    最後に、「上記のようにコードをつけて分離しようと思えばできる項目が複数あり、やるべきかやらざるべきかで悩んでおります。」の基準ですが、現実世界で、単独で存在し得る事項はコードをつける価値があると思ってください。(もし、今は必要ないが、実は、もっと項目がある可能性がある場合には、分ける価値がある可能性が高いです。例えば、人名。今は必要なくても、人名テーブルには性別や生年月日など他の項目がつく可能性があります。)  元の事例に戻ると、Genre_nameは単独で存在し得ますね。「SF」とか「ラブストーリー」とかは、なにも映画の世界に依存する分類項目ではないです。一方、これは極端な例ですが、w_dateは、この項目単独では価値がありません。  こう考えれば、少し解決の導入になるかもしれません。

kiro0000
質問者

お礼

お二方の意見を読ませていただき、 将来的なことも考えてコードをつけての第3正規化をやることにしました。 面倒くさいからやらないとかはDBの整合性とかを考えたらなしですね。 回答ありがとうございました。

その他の回答 (2)

  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.2

 正規化の必要性の第一の側面が、No.1の方が言われるようにデータの整合性をデータベース内で保つことです。この副作用として、データの拡張性も手に入れることができます。  このテーブルだけを見るならGenre_codeを無くせば、遷移従属性も無くなり第3正規性を手に入れることができます。ところで、例えば、書籍データも整理しようとしたら、どうしましょうか?似たような項目もあるでしょうが違う項目もありますから、まず、別テーブルを構築することになるでしょう。でも、Genre Tableはそのまま使えそうですね。映画も書籍も、まぁ、この手の分類項目は似たような物ですから。  ちゃんと正規化しておくと、このようなデータの転用が容易にできるようになります。さらに、映画と書籍の関連性も設計が可能になります。Genre_codeを無くしてしまえばという手を使った時にはできなかったことです。  さて、理論的に考えれば、正規化はできる限り上位の正規化を、最低でも、第3正規化までは行うべきとされています。これは、無限の資源があればの話。  現実のシステムでは、CPUパワーは有限の資源ですし、人間の時間も有限です。  そして、正規化を行うことによりテーブルを分けると言うことは、データを使う時に、テーブルを結合する必要があると言うことを意味します。この結合にかかるコストが大きすぎる時に、最適化の作業として、もう一度テーブルを統合するがあります。  ただし、このテーブルの統合も、正規化を崩すことによるデメリットと、手に入れられる性能を充分に比較考慮した上で、さらに、他に方法が無いかを検討した上で行うこととされています。それほどに、データの整合性をデータベースに任せられるという価値は大きいと言うことです。

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.1

・アクション、ラブストーリー、SF以外のジャンルが登場したら? ・SFを「サイエンスフィクション」に変更したい言われたら? ・ジャンルに「ラブストーリ」「Action」などと入れさせないようにするには? ・ジャンルコードの一覧を表示するには(まだ1件も登録がないものを含む)? 上記のようなニーズをすべてデータベース内で解決しようとするアプローチが正規化です。 楽をするためにやるのではなく、必要最小限の処理で整合性を保てるようにするためにやるものですね。 分けるかどうか迷ったら、上記のようなニーズが発生したときのことを考えれば判断できるかなと思います。 プログラム側で値を持つということは、その項目については、ある意味データベースでの整合性管理をあきらめたということです。 (データベースを見ても、構造やコードの意味が分からない)

関連するQ&A

  • 第3正規化とは何でしょうか

    データベースの第三正規化がよく分かりません。 第二正規化との違いがよく分かりません。 第2→主キーの一部に従属する項目を分離 第3→主キーに従属しない項目を分離 という説明があったり (このテキストでは、主キーを常に複合キーとしているようであり、その複合キーの(2つとして)どちらかを主キーとする表をつくるのが2で、その複合キーのどちらとも関係しない列を主キーとする表を3としているようなのですが、そもそも主キーは複合キーとは限らないはずだと思うのですが・・) 別のテキストでは(ある基本情報技術者試験のテキスト) 第2→関数従属 第3→推移的関数従属 という説明があったりします(推移的関数従属というのをネットで調べてみましたが、その概念がここでどう当てはまるのか分かりません) このへん教えていただけませんでしょうか? あるいは、分かりやすくある程度体系的に教えているページや本があれば教えてください。

  • また正規形について。

    http://www.techscore.com/tech/sql/16_02.html のURLの下の方の表 受注番号、商品番号、納入業者 12345  001   業者 A 12345  002   業者 B 12346  001   業者 A 12347  001   業者 D において、 ****以下引用**** このとき、非主キー列「納入業者」は「受注番号」と「商品番号」から決まりますので、(受注番号、商品番号) →納入業者は関数従属の関係が成立しています。よって、このテーブルは第二正規形の条件を満たしていると言えます。(中略) ****引用終わり**** とありますが、私には 商品番号→納入業者 という関数従属関係があるきがするのですが違うのでしょうか?なので第二正規形の時点で、 (商品番号、納入業者)という表が新たに分離される気がするのですが… さらに、 http://www.st.rim.or.jp/~ryoma/tips/seikika.htm のURLの同じくボイスコッド正規形で扱われ表、 商品コード、仕入先コード、担当者コード 000120001 111 401 000120001 112 402 000120002 111 401 000120002 150 403 仕入先コード、仕入先名 001 東京商店 002 大阪商会 003 名古屋流通 で、 *引用* 商品コード、仕入先コード、担当者コードを属性とする上の表は、繰り返し部分を持たず、また商品コード+仕入先コード、あるいは商品コード+担当者コードをキーとすることができ、かつ推移従属の関係が存在しないため、第三正規形です。 *終* とありますが、主キーを【商品コード、仕入先コード】と決めたとき、非候補キーである担当者コードは仕入先コードに関数従属している気が(私は)してしまうので第二正規形へ変形した時点で(仕入先コード、担当者コード)という表が分離されていると思うのですが。 以上の解釈で間違っている考えがあればご指摘ください。

    • ベストアンサー
    • MySQL
  • 正規化について

    こんばんは。お世話になっております。 現在、テーブルの設計を考えているのですが、「正規化」に関してアドバイスを頂ければと思い、投函させて頂きました。 例えば、ログイン情報に関する、id,mail,passwd,name1,name2,address,category などといった項目を格納させたいと思っているのですが、正規化を調べていると、更に細分化して登録させるべき・・などといった事が書かれていました。 当然、分散させるとスクリプト的にバグを誘発する可能性も出てくるかと思うのですが、データを参照する際、複数のテーブルに接続する負荷?を踏まえ、今回のような個人情報に関するものでも、分散して登録した方が良いのでしょうか? 有識者の貴重なご意見を頂戴出来れば幸いです。 お忙しい中恐縮ですが、宜しくお願い申し上げます。

    • ベストアンサー
    • MySQL
  • 正規化があっているのかどうか見てください。

    最近自作サイトを作っているのですが、DBの設計がちゃんと正規化されているか自信がありません。 そこで今考えているDBのテーブル設計を書かかせていただきますので、あっているかどうかチェックしていただきたいと思って投稿しました。 例えば電子書籍のDBを設計するとして、 ・漫画ID タイトル タグ ページ数 アクセス数 Upload日 Update日 こんなテーブルがあったとして、タグには複数の項目が入るので、第一正規化を適用して ・漫画ID タイトル タグID ページ数 アクセス数 Upload日 Update日 ・タグID タグ の2つにわけました。ここで2つ疑問があります。 まずタグIDとタグからなるテーブルですが、これの主キーはタグIDとタグですよね? これは主キー以外にレコードは無いんですが、こういう設計はまちがっていませんか? 次に、もう一個のテーブルがやけに長いというか第2正規化できるような気がするのですが、 部分関数従属するカラムは見当たりません。(例:ページ数が決まったかといって、アクセス数が決まるわけではない。 つまり全て漫画IDに完全関数従属している)。これであっているでしょうか? ご回答お待ちしております。

  • MySQL,PHPを使いデータとデータ件数を取得する関数

    よろしくお願いします。 このようなテーブルがあります。 テーブル名GAME id name    price  genre_id  comment 1 FF1    100  1  おもしろい 2 カービー 200 3 丸い赤 3 バイオ   250 2 怖い : : : : : テーブル名GENRE genre_id genre_name 1 RPG 2 ホラー 3 バイオ このようなテーブルがあるとして、 検索したいカラム(id,name,g_id,comment)に対して検索キーワードに部分一致をしたものデータからソートしたいカラムと昇順降順のようにソートしページ数から (ページ数-1)*10+1 ~ ページ数*10 最終ページのときは (ページ数-1)*10+1 ~ 最終ページ の部分のデータを取得する関数を作りたいです。表示するデータは id name genre_name です。 ページャーも使うので検索カラムにたいして検索ワードに部分一致した結果件数も戻り値として返したいです。 上記のsql文を教えてください。 またデータと結果件数を返す関数を作ることは可能でしょうか? 関数の引数は以下のように5つにするつもりです。 function getList($search_column,$search_word,$sort_column,$sort_order,$page_number) どうかご教授ください。

    • 締切済み
    • PHP
  • 正規化の仕方がわからず困ってます!助けて下さい。

    授業のレポートで郷土料理のデータベースを作っています。正規化をしてみたのですが、合っているのが分かりません。 本を見ながら自分なりに下のようにやってみました。 (1)非正規形 (材料、道具、行事名は複数あるため、材料ID、道具ID、行事ID以下それぞれ繰り返し) 料理ID・料理分類ID・料理分類名・料理名・料理名注解・調理方法・情報源・食べ方・料理に関する情報源・地域・写真の有無・補足情報・材料ID・材料名・旬の時期・栄養価・材料の入手方法(現在)・材料の入手方法(昭和中期~後期)・材料の入手方法(明治~昭和初期)・道具ID・道具名・行事ID・行事名・行事名注解・行事内容・地域・行事に関する情報源 (2)第一正規形 繰り返しをしている部分を分割しました。 ■料理テーブル 料理ID・料理分類ID・料理分類名・料理名・料理名注解・調理方法・どのような時に食べるか・料理に関する情報源・地域・写真の有無・補足情報 ■材料テーブル 料理ID・材料ID・材料名・旬の時期・栄養価・材料の入手方法(現在)・材料の入手方法(昭和中期~後期)・材料の入手方法(明治~昭和初期) ■道具テーブル 料理ID・道具ID・道具名 ■行事テーブル 料理ID・行事ID・行事名・行事名注解・行事内容・地域・行事に関する情報源 (3)第二正規形 部分キーにのみ従属するフィールドを分離しました。 ■材料_材料関連テーブル 料理ID・材料ID ■材料詳細テーブル 材料ID・材料名・旬の時期・栄養価・材料の入手方法(現在)・材料の入手方法(昭和中期~後期)・材料の入手方法(明治~昭和初期) ■道具_料理関連テーブル 料理ID・道具ID ■道具名テーブル 道具ID・道具名 ■行事_料理関連テーブル 料理ID・行事ID ■行事詳細テーブル 行事ID・行事名・行事名注解・行事内容・地域・行事に関する情報源 (4)第三正規形 主キー以外のフィールドに従属するフィールを分離しました。 ■料理テーブル 料理ID・料理分類ID・料理名ID・調理方法・どのような時に食べるか・情報源・地域・写真の有無・補足情報 ■料理分類テーブル 料理分類ID・料理分類名 ■料理名テーブル *ここで料理名IDを付けました。 料理名ID・料理名・料理名注解 ■行事詳細テーブル 行事ID・行事名ID・行事内容・地域・情報源 ■行事名テーブル 行事名ID・行事名・行事名注解 *ここで行事名IDを付けました。 これで合っているのでしょか??全く自信が無いです。 どう考えても料理テーブルがごちゃごちゃしています。 どのように整理したらよいか教えてください。よろしくお願いします。

  • PHPにおける正規表現について

    PHPにおける正規表現について ご教授ください。 いわゆる、対象の文字列が複数行にわたっていた場合のことです。 $data = <<< EOF ABCDE FGH EOF; $hoge = preg_match("/EF/" ,$data,$match); と上記のようなコードがあった場合 対象の文字列群から【EF】という文字列を検索したい場合、どのように記述したら 【E(間に改行)F】の文字列と一致させる事ができるでしょうか? 仮に正規表現の修飾子の【s】や【m】を用いても上記の例の場合 一致させることができないと思います。 やはり、対象の文字列群 $data の改行文字をいったん削除したものから検索 するのがベターでしょうか? 正規表現に造詣の深い方よろしくご教授ください。

    • ベストアンサー
    • PHP
  • SQL (ORACLE)について

    こんにちは。 SQL文について教えてください。 【temp1テーブル】 code name value 001 yama 100 002 kawa 200 003 umi 300 【temp2テーブル】 code name value 002 kawa 200 004 minato 500 上記の2つのテーブルtemp1とtemp2を比較して codeの値とnameの値が同じレコードの場合 temp1のvalue値を temp1のvalue + temp2のvalueにする 方法を教えて頂けませんでしょうか。

  • cakephpでの開発

    初めまして、新人プログラマーです。 最近、cakeを使って開発をするプロジェクトに参加する事になったんですが、よく分からないので質問させて頂きます。 DBにある二つのテーブルから関連した情報を取得したいんですが、 1つ目は itemsテーブル id unit_price_code item_name item_code small_categories price 2つ目は unit_pricesテーブル id unit_price_code name created modefied という感じで2つの共通カラムはunit_pride_codeになります。 unit_pricesテーブルの各カラムは一意なんですが、itemテーブルに関してはunit_price_codeが同じものでitem_name、item_codeが違うものがあります。 取得したい項目はまず2つのテーブル共通のunit_price_codeをキーにしてitmesテーブルのitem_name、item_code、unit_priceテーブルのmodefiedとなります。 分かりにくい説明で申し訳ないんですが、ご回答宜しくお願いします(汗)

    • 締切済み
    • PHP
  • SQLの書き方

    テーブルA CODE NAME ------------- 0001 山田 0002  斎藤 0003 宮下 テーブルB CODE NAME ------------- 0002  斎藤 0004 加藤 上記のテーブA,Bから下のような結果を 返すSQL分を書きたいのですが何かよい方法はないでしょうか? (重複する行は一行として返したいです。) CODE NAME ------------- 0001 山田 0002  斎藤 0003 宮下 0004 加藤