• ベストアンサー

共通のカラムを持つテーブルの外部キーの設定

MySQLバージョン4.1.16を使用しています。 2つのテーブル「tbl1」と「tbl2」があり、 それぞれ共通のカラムを別のテーブル「common_tbl」に設定(正規化)し そのcommon_idを「tbl1」と「tbl2」が参照します。 例えば、「tbl2」にデータをinsertする場合に、 まず「common_tbl」からinsertして、そのinsert_idを取得(利用)して 「tbl2」にデータを挿入します。 たぶんこの場合のinsertはこのようなやり方だと思います(あまり自信ないなぁ・・・) 「tbl2」の行を削除した場合に、「common_tbl」の行も自動で削除させたいと思うのですが、 どのように外部キーを設定するのか(どこに設定するのか)が分かりません。 「common_tbl」に「tbl1」のtbl1_idと「tbl2」のtbl2_idを それぞれ持たせるのはたぶん違うと思いますし・・・ この場合の正しいテーブル構成を含めてアドバイスをお願いしたいです。 例: 「tbl2」のtbl2_idが2の行を削除したら、 「common_tbl」のcommon_idが3の行も削除したい(外部キーで自動的に) テーブル「tbl1」 +------+---------+----------+ | tbl1_id| tbl1_col1 |common_id | +------+---------+----------+ |  1  |   値1  |   1    | +------+---------+----------+ テーブル「tbl2」 +------+---------+----------+----------+ | tbl2_id| tbl2_col1 | tbl2_col2 |common_id | +------+---------+----------+----------+ |  1  |   値1  |   値1  |    2   | +------+---------+----------+----------+ |  2  |   値2  |   値2  |    3   | +------+---------+----------+----------+ テーブル「common_tbl」 +----------+---------+----------+ |common_id |   col1  |   col2  | +----------+---------+----------+ |  1     |   値1  |   値1  | +----------+---------+----------+ |  2     |   値2  |   値2  | +----------+---------+----------+ |  3     |   値3  |   値3  | +----------+---------+----------+

  • MySQL
  • 回答数2
  • ありがとう数2

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

  • ベストアンサー
回答No.2

>主たる(削除したりする場合の優先順位のようなもの) >テーブルは「医者テーブル」や「教師テーブル」ですよね? >そうだとしたら、「医者テーブル」のある行を削除したら(ある医者が辞めたら) >「人情報テーブル」の対応してる行も削除されるというのが普通だと思う 一人で複数の職業を兼業していたり、一時的に無職になったり、転職することもある訳ですから、特定の職業を辞めたからといって、その人の基本情報を削除していいということにはならないのでは? 何を管理することを主目的にしているかにもよりますが、一般的には各人の基本情報を管理するテーブルがあり、そこから職業、資格、扶養家族などを管理するテーブルが関連づく構成にすると思います。

takagoo100
質問者

お礼

ご返答ありがとうございます。 たしかに言われてみれば人情報を主にした方が良さそうですね。 その場合、 >一人で複数の職業を兼業していたり、 は、どのようなテーブル構成になるのでしょうか? 職業が1つだけなら下のような構成でいいのでしょうが、 例えば「人_tbl」の人_idが1の人が、 教師と医者の2つの職業を持っていた場合の構成と CASCADE方法が知りたいです。 テーブル「人_tbl」 +----------+---------+----------+ |  人_id   |   年齢 |   職業_id| +----------+---------+----------+ |  1     |   32   |   教師 | +----------+---------+----------+ |  2     |   45   |パイロット | +----------+---------+----------+ テーブル「職種_tbl」 +----------+---------+ |  職業_id |   年収  | +----------+---------+ |  医者   | 2000万  | +----------+---------+ |  教師   | 600万  | +----------+---------+ | パイロット | 1500万  | +----------+---------+

takagoo100
質問者

補足

すいません、たぶん自己解決しました。 つまり「人_tbl」に職種_idというカラムを設ける必要がなくて 新たに「職業_tbl」というテーブルを作成すれば良さそうです。 なんか勘違いしてました・・・ 「職業_tbl」の人_idを外部キーに設定したりというぐあいに。 まだ頭の中が整理しきれてないですが、これらを考えていきたいと思います。 テーブル「人_tbl」 +----------+---------+ |  人_id   |   年齢 | +----------+---------+ |  1     |   32   | +----------+---------+ |  2     |   45   | +----------+---------+ テーブル「職種_tbl」(←適切な名前が浮かばない・・・) +----------+---------+ |  職種_id |   年収  | +----------+---------+ |  医者   | 2000万  | +----------+---------+ |  教師   | 600万  | +----------+---------+ | パイロット | 1500万  | +----------+---------+ テーブル「職業_tbl」(←適切な名前が浮かばない・・・) +-------+-------+-------+ |  id   | 人_id | 職種_id| +-------+-------+-------+ |  1   | 1    | 医者 | +-------+-------+-------+ |  2   | 1    | 教師 | +-------+-------+-------+ |  3   | 2    |パイロット| +-------+-------+-------+

その他の回答 (1)

  • auty
  • ベストアンサー率58% (284/486)
回答No.1

試してみてはいませんが、 -------------------------------------------------------------------------------- CREATE TABLE tbl1 ( tbl1_id integer, ... ,common_id integer, Primary Key (tbl1_id), Foreign Key (common_id) references common_tbl(common_id)) TYPE = InnoDB; Primary Keyがない時は、CREATE INDEX ind1 ON tbl1 (tbl1_id); -------------------------------------------------------------------------------- CREATE TABLE tbl2 ( tbl2_id integer, ... ,common_id integer, Primary Key (tbl2_id), Foreign Key (common_id) references common_tbl(common_id) TYPE = InnoDB; Primary Keyがない時は、CREATE INDEX ind2 ON tbl2 (tbl2_id) ; -------------------------------------------------------------------------------- たとえば、テーブル「tbl2」に、「FOREIGN KEY 制約」を設けるときに、ON DELETE CASCADE 節を付加できますが、 これは、テーブル「common_tbl」からレコードを削除するときに連動して テーブル「tbl2」のレコードも削除するというものです。 逆を自動的にやるのは無理だと思います。 ・ まず、テーブル「tbl2」から削除して、 ・ 次に、テーブル「common_tbl」から対応するレコードを削除する   (このときもし対応するレコードがテーブル「tbl1」にある場合は失敗する。) *  テーブル「tbl2」からも削除してよければ、まさにテーブル「common_tbl」から対応するレコードを削除すれば一発で処理は完了となると思います。 利用するための条件(主キー、インデックス、どちらもInnoDBテーブル型)については、 以下のページを参考にしてみてください。 http://dev.mysql.com/doc/refman/4.1/ja/innodb-foreign-key-constraints.html http://synth.jp/pg/2007/06/mysql_primary_keyforeign_key.html

takagoo100
質問者

お礼

ご返答ありがとうございます。 なるほど、「tbl1」や「tbl2」の方に外部キーを設けるということですか。 ただこの場合の主役(先に操作するテーブル)は「tbl1」や「tbl2」だと思うんです。 なので「common_tbl」から削除して「tbl1」や「tbl2」が 削除されるというのは、なんとなく違和感があって・・・ 例えば、「tbl1」や「tbl2」を1つのテーブルで纏めることが できない(カラム数などに違いがある)と仮定として、 職業情報 「tbl1」=「医者テーブル」 「tbl2」=「教師テーブル」 共通の人間 「common_tbl」=「人情報テーブル」 とした場合、主たる(削除したりする場合の優先順位のようなもの) テーブルは「医者テーブル」や「教師テーブル」ですよね? そうだとしたら、「医者テーブル」のある行を削除したら(ある医者が辞めたら) 「人情報テーブル」の対応してる行も削除されるというのが普通だと思うんです。 そもそもこの自分が考えたテーブル構成自体間違っているような気がするのですが、 こういうケースではどのようなテーブル構成、そしてCASCADEさせればベストなのでしょうか?

関連するQ&A

  • 別テーブルからselectした値を他のテーブルにinsertしたいのですが、上手くできません

    以下のように行ったのですが、 全ての値が別テーブルにinsertされません。 $sql = "SELECT tbl_A.id, tbl_A.data FROM tbl_A "; $rst = mysql_query( $sql ); while ( $col = mysql_fetch_array( $rst ) ) { $sql = "INSERT INTO tbl_B (          date, id, data ) VALUES ( '" . date( 'Y-m-d' ) . "', '" . mysql_real_escape_string( $col['id'] ) . "', '" . mysql_real_escape_string( $col['data'] ) . "' )"; } このやり方では、テーブル内の1つの値しかinsertされません。 selectされた全ての値をinsertするにはどのようにしたら良いのでしょうか? よろしくお願いします。 DB:mysql5 SP:php5

    • ベストアンサー
    • MySQL
  • 複数テーブルに同一の外部キーやカラムがある場合

    例えば、ホテルテーブル、レストランテーブル、映画館テーブルなど施設別のテーブルが多数あり、 そのそれぞれが、所在エリアを示すエリアIDを持つ場合、テーブル1つずつにエリアIDを外部キーとして持たせるか、施設テーブルという抽象的なテーブルを作り、そこにエリアIDを持たせ、具体的なホテルテーブルなどは施設テーブルと1対1で結びつけるべきか、迷っていますが、どちらがいいでしょうか? エリアID以外にも共通のカラムがあります(名称、住所など)。 今後、具体的な施設テーブルは増える可能性があります(遊園地テーブルなど)。 また、エリアID以外にも共通の外部キーも増える可能性があります(所有会社IDなど)。 そう考えるとテーブル1つずつにリレーションを付けるとER図が線だらけになる気がします。 しかし抽象テーブルを作ると、データを取ってくるたびに毎回JOINしないといけないのが気になります。 ご意見お願いします。

  • 別テーブルのカラムを利用してソートしたい

    別テーブルのカラムを利用してソートしたい MySQLバージョン4.1.16を使用しています。 テーブル「tbl1」をテーブル「tbl2」のcountというカラムを利用して ソートしたいのですが、どのようなSQL文になるのでしょうか? 「tbl2」のidというカラムは外部キーで「tbl1」のidと関係しています。 テーブル「tbl1」 +------+---------+ |   id |  userid  | +------+---------+ |  1  | tanaka  | |  2  | sato   | +------+---------+ テーブル「tbl2」 +------+---------+ |   id |  count  | +------+---------+ |  1  |   10  | |  2  |   3   | +------+---------+ 次のような文かなと思ったのですが、エラーが返ってきます・・・ SELECT * FROM tbl1 ORDER BY (SELECT id FROM tbl2 ORDER BY count)

    • ベストアンサー
    • MySQL
  • sqlservrのシステムテーブルから主キー判定

    sqlservrのシステムテーブルのから主キーの判定を行いたいです。 sysobjects(type='U')でテーブル情報があり、それに紐付くsyscolumnsの項目情報があるとします。 テーブル名,項目名 tbl1,item1 tbl1,item2 tbl1,item3 tbl2,item1 tbl2,item2 これは、 select obj.name as "テーブル名" , col.name as "項目名" from sysobjects obj left join syscolumns col on obj.id = col.id where obj.type = 'U' で取得できますが、 さらに、主キーの項目には○をつけたいです。 テーブル名,項目名,主キー tbl1,item1,○ tbl1,item2,○ tbl1,item3,null tbl2,item1,○ tbl2,item2,null sysindexkeysやsysindexesの情報を引っ掛ければなんとかなるかと思いましたが、何ともならずにGive UP状態です。 システムテーブルを結合して取得する方法はありますでしょうか?

  • 2つの関連するテーブルで指定した値を条件に取得したい

    mysql5.1.33を使用しています。 次のような構成で、 テーブル「tbl1s」 id int(11) テーブル「tbl2s」 id int(11) name varchar(30) テーブル「tbl1s_tbl2s」 id int(11) tbl1_id int(11) tbl1sの外部キー tbl2_id int(11) tbl2sの外部キー テーブル「tbl1s」 +------+ |  id  | +------+ |  1  | +------+ |  2  | +------+ |  3  | +------+ テーブル「tbl2s」 +------+-------+ |  id  | name | +------+-------+ |  1  | sato  | +------+-------+ |  2  | suzuki | +------+-------+ |  3  | tanaka | +------+-------+ テーブル「tbl1s_tbl2s」 +------+-------+-------+ |  id  | tbl1_id | tbl2_id | +------+-------+-------+ |  1  | 1    | 1   | +------+-------+------+ |  2  | 1    | 2   | +------+-------+------+ |  3  | 3    | 1   | +------+-------+------+ 「tbl1s」テーブルの行を「tbl2s」テーブルのnameを検索条件にして取得したいのですが どのように記述すれば良いのでしょうか? 例えば「sato」を条件にした場合は、 テーブル「tbl1s」 +------+ |  id  | +------+ |  1  | +------+ |  3  | +------+ を取得したいです。

    • ベストアンサー
    • MySQL
  • 複数のカラムを対象にしたプライマリキー制約の設定

    テーブル作成後に複数のカラムを対象にしたプライマリーキー制約を設定することはできるのでしょうか。 テーブル作成時であれば、次の方法により設定することができます。 ※col_name1及びcol_name2に設定したい場合 CREATE TABLE tbl_name (col_name1 int NOT NULL, col_name2 int, col_name3 varchar(255), PRIMARY KEY(col_name1, col_name2)); しかし、一旦テーブルを作成した後に、プライマリーキー制約を設定し忘れたことに気が付き、設定したい場合は、いかなる方法によりできるのでしょうか。 次の方法にて試みたものの、エラーが生じました。 【SQL文】 ALTER TABLE tbl_name MODIFY col_name1 int, col_name2 int, PRIMARY KEY(col_name1, col_name2); 【エラー内容】 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'col_name2 int, PRIMARY KEY(col_name1, col_name2)' at line 1 テーブルを削除し、再作成時にプライマリーキー制約を設定する方法によっても対応できますが、削除しなくてもこれを行える方法があるのか否かを知りたく、質問させていただきました。

    • ベストアンサー
    • MySQL
  • 2つの関連するテーブルの並び替え

    mysql5.1.33を使用しています。 テーブル「tbl1」 id int(11) テーブル「tbl2」 id int(11) num1 int(11) テーブル「tbl1_tbl2」 id int(11) tbl1_id int(11) tbl1の外部キー tbl2_id int(11) tbl2の外部キー テーブル「tbl1」 +------+ |  id  | +------+ |  1  | +------+ |  2  | +------+ |  3  | +------+ |  4  | +------+ テーブル「tbl2」 +------+------+ |  id  | num | +------+------+ |  1  | 5  | +------+------+ |  2  | 10  | +------+------+ |  3  | 50  | +------+------+ |  4  | 100 | +------+------+ テーブル「tbl1_tbl2」 +------+-------+-------+ |  id  | tbl1_id | tbl2_id | +------+-------+-------+ |  1  | 1    | 2   | +------+-------+------+ |  2  | 1    | 3   | +------+-------+------+ |  3  | 2    | 1   | +------+-------+------+ |  4  | 4    | 4   | +------+-------+------+ というテーブル構成で、tbl1の所有するtbl2のnum1の平均値によって降順にソートしたいのですが どのようなSQL文になるのでしょうか? 例えばこの場合では、 tbl1のid「1」は、(tbl1_tbl2のid1「1」のtbl2_idのnum(10)+ tbl1_tbl2のid1「2」のtbl2_idのnum(50))÷2=30 tbl1のid「2」は、(tbl1_tbl2のid1「3」のtbl2_idのnum(5))÷1=5 tbl1のid「3」は、tbl1_tbl2にないので=0 tbl1のid「4」は、(tbl1_tbl2のid1「4」のtbl2_idのnum(100))÷1=100 なので テーブル「tbl1」は +------+ |  id  | +------+ |  4  | +------+ |  1  | +------+ |  2  | +------+ |  3  | +------+ に並べ変えられた結果が得たいです。

    • ベストアンサー
    • MySQL
  • 2つの関連するテーブルで指定した値を条件orで取得したい

    mysql5.1.33を使用しています。 次のような構成で、 テーブル「tbl1s」 id int(11) テーブル「tbl2s」 id int(11) name varchar(30) テーブル「tbl1s_tbl2s」 id int(11) tbl1_id int(11) tbl1sの外部キー tbl2_id int(11) tbl2sの外部キー テーブル「tbl1s」 +------+-------+ |  id  | club | +------+-------+ |  1  | 野球 | +------+-------+ |  2  | テニス| +------+-------+ |  3  | サッカー| +------+-------+ +------+-------+ テーブル「tbl2s」 +------+-------+ |  id  | name | +------+-------+ |  1  | sato  | +------+-------+ |  2  | suzuki | +------+-------+ |  3  | tanaka | +------+-------+ テーブル「tbl1s_tbl2s」 +------+-------+-------+ |  id  | tbl1_id | tbl2_id | +------+-------+-------+ |  1  | 1    | 1   | +------+-------+------+ |  2  | 1    | 2   | +------+-------+------+ |  3  | 3    | 1   | +------+-------+------+ というテーブル構成で、「tbl1s」テーブルの行を 「tbl1s」のclubかない場合には「tbl2s」のnameを検索条件にして取得したいのですが どのように記述すれば良いのでしょうか? 例えば「テニス」を条件にした場合は、「tbl2s」のnameにはないですが「tbl1s」のclubには合致するのがあるので テーブル「tbl1s」 +------+ |  id  | +------+ |  2  | +------+ を取得したいです。

    • ベストアンサー
    • MySQL
  • 外部キーの設定方法について

    外部キーの設定方法について テーブルCのカラムCについて、テーブルAのカラムA、またはテーブルBのカラムBにある値しか受け付けないように、外部キーの設定を行いたいのですが、方法が分かりません。 テーブルAのカラムAとテーブルBのカラムBとをUNION したビューを作成してみましたが、ビューにはプライマリィキーを設定することが出来なく、外部キーは作成できませんでした。 何か、回避策を教えてください。 よろしくお願いします。 データベースは、ANSI標準サポートのタイプとして、考えてください。

  • テーブルの自動キー再割り当て

    以下sqlでテーブルhogeを作成し、idを自動キーにしています。 CREATE TABLE `hoge` ( `id` INT NOT NULL AUTO_INCREMENT, ........(省略).......... PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=sjis; このテーブルのレコード番号4を削除するとテーブルのidは 1,2,3,5(最終)になり, 新しいデータを追加(INSERT)するとidは 1,2,3,5,6(最終)とid番号4が欠番になります。 テーブルのidを1,2,3,4,5と続き番号に再割り当てして、新しいレコードがid番号6の挿入されるようにするにはどのようにすればよいでしょうか? sql文をご教示い頂きたくよろしくお願いします。