複合キーの利用方法とテーブル構成の選択

このQ&Aのポイント
  • Perl+RDBMSを利用してWEBシステムの構築を考えております。既存の複合キーに連番を追加する方法について尋ねます。
  • 複合キーと人工キーを用いたテーブル構成の違いについて相談します。親子関係のテーブルにおいて、どちらの構成が正規化に適しているかについて教えてください。
  • テーブル構成における複合キーと人工キーの利点と欠点について知りたいです。複合キーは一気に参照できないが管理しやすい一方、人工キーは参照が容易であるが管理が煩雑になります。どちらを選ぶべきかアドバイスをお願いします。
回答を見る
  • ベストアンサー

複合キーの利用方法

はじめまして。 Perl+RDBMSを利用してWEBシステムの構築を考えております。 テーブルの組み方についてご意見伺えればと思います。 【質問】 1) 私は作成するテーブルに対して、既に存在している複合の項目で一意性が保たれていたとしても、必ず連番(serial id)の項目を追加しそれを主キーとしております。 このやり方は何か問題ありますでしょうか? 2) 質問1)に関連しているのですが、以下の例を元に、テーブル構成を2パターン記載致しますので、どちらの構成のほうがベター(或いはスタンダード)かをご助言頂ければと思います。 <例> --------------------- 親子関係のテーブル Table A └ Table B └ Table C --------------------- <考えられる上記例のテーブル構成> --------------------- 【P1-人工キーを用いた構成】 Table A:{A_ID} Table B:{B_ID},A_ID Table C:{C_ID},B_ID 【P2-複合キーを用いた構成】 Table A:{A_ID} Table B:{B_ID,A_ID} Table C:{C_ID,B_ID,A_ID} --------------------- 私が用いているのはP1の構成です。P1の構成を用いた場合の認知している問題点は、Table Cから一気にTable Aを参照できないことにあると思っております。 対してP2の場合、P1の問題は解決しますがテーブルのレイヤーが下がれば下がるほど、追加しないとならない項目が増えてしまって、管理の面やデータ量、またPG作成でも面倒が発生してしまうと思っています。 どちらのパターンが正規化などの観点から見ても良いものなのでしょうか? 長文申し訳ございません。 よろしくお願い致します。

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

  • ベストアンサー
  • angband
  • ベストアンサー率51% (86/168)
回答No.2

>申し訳ございません、この部分は例えばどのような場合になるのでしょうか? > この例でいきますと、内容が同じ受注を2つ受けた場合に、 TableB(受注明細情報(作業内容))とTable C(受注明細に付属する オプション(作業場所))の両方が重複するように思います。 (【P1-人工キーを用いた構成】の場合) 逆に上記のケースでレコードが重複しない場合は、TableBとTableCには 同じ内容のレコード(主キーだけ違う)が許されるわけで、その場合は 第二正規形でなくなってしまうように思います。 フィールド内容の実世界での関係によりますが、話をうかがっている限りでは TableCが実際には、TableAに関係があるように思ってしまってます。 ここで本当にTableCがTableBだけの依存で関係を表現できるかが大切に 思えます。(勘違いだったらすいません) ---------------- >以下、別の質問になってしまうかもしれませんが・・・ これは難しい問題ですね。僕もよく悩みます。例えば会員を扱っている テーブルで、法人区分が個人か法人かで、個人名か会社名どちらかが必要な 場合などですよね。ちょっと調べてみます。 ・・

myosuke
質問者

お礼

度々のご回答有難うございました。 >・・・その場合は第二正規形でなくなってしまうように思います。 なるほど、人工キーを主キーとしたTableCが存在したら確かに主キーから見た従属関係はなくなってしまいますね。 気づいておりませんでした。有難うございます。 > ここで本当にTableCがTableBだけの依存で関係を表現できるかが大切に思えます。(勘違いだったらすいません) あ、いえ、ストライクです(笑)依存関係の視点で見てみるということですね。確かに私の頭の中ではCはAに依存していることが前提となっておりましたが、人工キーを用いた場合にはその前提を表現しきれておりませんでした。こちらも良く理解できました。有難うございます。 > これは難しい問題ですね。僕もよく悩みます。例えば会員を扱っている・・・ まさにそのような場合です。 DB構成は正解が見えにくい(というかあるのでしょうか 汗)ので、決定にはいつも悩まされますね。。 ですので、こういう場でも他の人の意見は大変参考になります。有難うございます。

その他の回答 (1)

  • angband
  • ベストアンサー率51% (86/168)
回答No.1

1)主キーを連番で作るのは良いアイデアだと思います。 2)ぱっと見たところでは、P1は問題があるように見えます。 TableAとTableBは1対多の関係かと思います(親子なので)。 でもTableCはTableBに対して、1対多だとレコードが重複するのではないですか? 1対1だとすると正規化の観点からはTableBとTableCは1つのテーブルで よいように思います。

myosuke
質問者

お礼

ご回答有難うございます。 > でもTableCはTableBに対して、1対多だとレコードが重複するのではないですか? 申し訳ございません、この部分は例えばどのような場合になるのでしょうか? 度々ですがご教授頂ければ幸いです。 > 1対1だとすると正規化の観点からはTableBとTableCは1つのテーブルでよいように思います。 以下、別の質問になってしまうかもしれませんが・・・ 補足に記載した例のような場合だとよく発生するのですが、特定の条件化によって入力対象の項目が異なってくる場合があります。 例えば、あるテーブルの項目<1>に○が入力される場合は項目<2>にデータを入力、×が入力される場合は項目<3>にデータを入力、といった時です。 そのような場合、項目<2>と<3>は別テーブルにし、項目<1>が存在するテーブルとは1:1の関係にしているのですが、こういったことは普通、行わないものなのでしょうか?第3正規化に引っかかるのでしょうか・・・

myosuke
質問者

補足

質問文の例のところで、インデントがおかしく、Table BとTable Cが並列かのように見えてしまっていますが、文章にすると以下のような関係です。 TableBの親はTableA。 TableCの親はTableAとTableB。 具体例をひとつ出しますと、 Table Aは受注情報(受注No) Table Bは受注明細情報(作業内容) Table Cは受注明細に付属するオプション(作業場所) といった感じです。 AとBの関係は1:M、BとCの関係も1:Mになります。

関連するQ&A

  • 再投稿:フィールドの値をテーブル名&フィールド名にして参照したい

    すみません。若干記入ミスだったので再投稿します。 こちらにご解答お願いします。 TABLE_a ・Ta_id ・key_table ・key_field ・key_no TABLE_b ・Tb_id ・Tb_name TABLE_c ・Tc_id ・Tc_name と3つのテーブルがあり、 key_tableに「TABLE_b」、key_fieldに「Tb_id」が入ってて、 TABLE_aとTABLE_bを select の left join して抽出したい場合、 どういうSQL文になるのでしょうか。 select * from TABLE_a left join case key_table when 'TABLE_b' then 'TABLE_b' when 'TABLE_c' then 'TABLE_c' end on 'TABLE_a.key_field'.key_no = case key_table when 'TABLE_b' then ''TABLE_a.key_table'.Tb_id' when 'TABLE_c' then ''TABLE_a.key_table'.Tc_id' end ; とやってみたのですが、うまくできませんでした。 ご教示お願いします。

  • テーブルのどちらかにデータがない事があるテーブル結合について

    ■table a のテーブル構成 date a_id b_id c_id a_count ■table b のテーブル構成 date a_id b_id c_id b_count value 上記の2つのテーブル構成から、 ■date a_id b_id c_id毎の集計データ date a_id b_id c_id a_count b_count value を抽出するSQLが知りたいです。 table aにあって、table bに存在しない。又は逆もある為、 union しかないと思うのですが、思いつきません。。

    • ベストアンサー
    • MySQL
  • 3つのテーブルの画面表示

    Access 2013 vba リレーションが貼ってある親子関係の3つのテーブルがあったとして・・・ A table: ・ID1(主キー) ・依頼会社ID ・依頼内容 ・金額総合計(Bの会社毎の金額の合計) B table: ・ID2(主キー) ・ID1(外部キー) ・会社ID ・金額計(Cの明細の金額の合計) ・完了日 ※AのID1 : BのID1 = 1 : 多 C table: ・ID3(主キー) ・ID2(外部キー) ・項目名 ・単位 ・数量 ・金額 ※BのID2 : CのID2 = 1 : 多 このようなテーブル構成がある場合に まず、AとBの画面を作りそこでBの情報を入力して 次に、Bの帳票のどれかを選ぶと、 BとCのメイン・サブフォームが表示され、そこでCの明細を入力するというやり方も考えていますが、もう一つ、1つの画面で、BとCを両方サブフォームとして配置し、Bの方のレコードを選択すると、Cの方でそれに対応する明細が表示できるようなものを作りたいです。 このような方法が可能か教えていただきたいのと、その場合のやり方を教えて下さい。 宜しくお願いします。

  • accessで複合キーの処理が遅い

    あるマスタデータと明細データがありキーとなる列が2つ(2列)あります マスタデータのテーブルのキー列のA列、B列を主キーとして定義し 明細データのテーブルのキー列のA列は重複ありのインデックス B列も重複ありのインデックスとしてそれぞれ設定しています その2つのキーをクエリで結合して更新する更新クエリを作成しているのですが データ量が多くなってくると非常に反応が遅くなります 同じデータ量で 2つのキー列の値をあるひとつの列に結合した値を格納しその結合列で 更新クエリを作成したところ高速に処理が動作しましたので 複合キーだった場合の処理速度が遅いのだと推測しました (※C列にA列 & B列 の結合した値を格納してC列をキーにするという事です) accessで複合キーの更新クエリを作成する場合、高速に動作させるには なにか工夫が必要なのでしょうか? アドバイス下さい 上記のように複数のキーをひとつの列に結合する工夫で早くはなったのですが・・・ 余分なデータを格納する事になるので非常に容量が大きくなってしまう問題があります

  • 外部キーが設定されているテーブルのupdateについて

    PostgreSQL8.24を利用しています。 pgADMINIIIでテーブルを作成しました。 【TABLE_A】と【TABLE_B】があります。 【TABLE_A】の【ID】が【TABLE_B】の【ID2】が外部キーとして設定してあります。 CONSTRAINT TABLE_B_fkey FOREIGN KEY (ID2) REFERENCES TABLE_A (ID) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION 上記のように記述されています。 SQL文のUPDATEを使い、IDが「01」を「05」に更新したいのですが、 以下のように記述するとエラーになります。 どのようなUPDATE文を記述すればよろしいのでしょうか。 UPDATE TABLE_A INNER JOIN TABLE_B on TABLE_A.ID=TABLE_B.ID2 SET TABLE_A.ID = '05',TABLE_B.ID2 = '05' WHERE TABLE_A.ID='01'" よろしくお願いいたします。

  • テーブルの差分を抽出する方法

    TSVファイルが送られてくるたびに 1.CREATE TABLE 2.データ格納 しているのですが、前回と今回で送られたレコードの差分を抽出する、良い方法ありますでしょうか? 同じ構成のテーブルを2つ用意するとなんとなく比較しやすそうですが、そこから先が思いつきません。 ■作成するテーブル(PKは複合キーで項目AとBです)  A B C D  1 2 xx yy  2 3 aa bb

  • 同じフィールドを複数条件指定して検索をする場合

    やりたいこと。 あるものに対して識別する種別と項目から個体を設定する。 複数種別の識別項目から検索をしたい。 table_a id_a が 個体ID id_b が 個体識別種別ID id_c が 個体識別項目ID table_b s_id が 個体識別種別ID s_name が 個体識別種別名 table_c k_id が 個体識別項目ID k_name が 個体識別項目名 k_sid が 個体識別種別ID 条件: table_aは id_aとid_bでユニークな値になる。 table_cのk_idはユニーク値。 識別種別(table_b)は無制限に増える可能性がある 識別項目(table_c)も無制限に増える可能性がある 種別が可変なのでtable_aに種別分のフィールドを作ることができない。 例) Aさんは手が二本で頭は悪い。 Bさんは手が二本で頭は良い。 Cさんは手が四本で頭は普通。 Dさんは手が複数で頭は悪い。 table_a(id_a,id_b,id_c) A,1,1 A,2,4 B,1,1 B,2,5 C,1,2 C,2,6 D,1,3 D,2,4 table_b(s_id,s_name) 1,手 2,頭 table_c(k_id,k_name,k_sid) 1,1,二本 2,1,四本 3,1,複数 4,2,悪い 5,2,良い 6,2,普通 検索:手が二本で頭が良い人 結果:A 以上のことをやるにはどのようにしたら良いでしょうか。 テーブル構造が悪い場合変更することも検討しています。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • ある条件でのSQLの取得方法について

    以下の条件でのSQLのデータの取得方法が分かりません。 2つのテーブルがあるとします。 ・テーブルA キー   項目1 10     X 20     Y ・テーブルB キー  項目2  項目3 10     5    C 10     6    D 12     6    E ここで取得する条件として ■テーブルAにあるのは、必ず取得します。 ■テーブルAのキーとテーブルBのキーは繋がり、繋がったテーブルBの情報は  別レコードとして取得します。 ■テーブルAのキー1つに対して、テーブルBのキーは無いかも知れないし、  複数件あるかも知れません。  無い場合はテーブルAの情報のみを出力し、複数件ある場合はその全てを出力します。 ■テーブルBの項目2が同じ値のデータがある場合、テーブルBを出力したレコードと  同じレコードに、項目2が同じデータの情報を出力します。  項目2が同じデータが無い場合はこの情報は出力しません。  項目2が同じ値のデータは最大2件しかありません。 上記の例の場合に出力したい結果 ・出力テーブルC キー  フラグ   項目1  項目2  項目3   項目2が同じキー  項目2が同じ値 10  テーブルA   X 10  テーブルB         5    C 10  テーブルB         6    D        12            E 20  テーブルA   Y (テーブルC のフラグとは、テーブルAの情報かテーブルBの情報かを示します) これを出来ればSQL、出来なければPL/SQLで取得したいのですが どちらの場合でも取得の方法に悩んでいます。 どのような方法で取得できるのでしょうか?

  • テーブルのマッチングについて

    ORACLE10gを使用しています。 AとB同じレイアウト(キーも同じ)のテーブルがあります。 この2つのテーブルを比較して、 (1)Aテーブルのみにあるもの:1レコードCテーブルに追加 (2)Bテーブルのみにあるもの:1レコードCテーブルに追加 (3)A、B両方にあるもの:2レコードCテーブルに追加 上記に該当するレコードをCテーブルにINSERTしたいです。 実は、Cテーブルに項目が1つ追加されまして「区分」を書く必要があります。 どのパターン((1)か(2)か(3))でINSERTしたデータかです。 (1):1、(2):2、(3):3をセットする どのようにSQLを作成すると実現できるのでしょうか? ご指導よろしくおねがいします。

  • SQLについて教えてください

    お世話になります。 SQLについて教えてください AテーブルとBテーブルからCテーブルを作成したいのですが、 KEYをキーにAテーブルのIDが1で、YYMMが一番新しい項目(最大の項目)を 取得し、Cテーブル作成したいのですが、どのようにするのでしょうか? Aテーブル    Bテーブル   Cテーブル KEY ID yymm   KEY     KEY YYMM AAA 0 200612  AAA     AAA 200611 AAA 1 200611  BBB     BBB 200611 AAA 1 200609 BBB 0 200611 CCC 1 200611