別々のテーブルで共通のidを使う方法はないでしょうか?

このQ&Aのポイント
  • 一つのページから別々のテーブルにデータをINSERTする方法について説明します。
  • データのINSERT時に同じ値を持つ「id」と「number」をそれぞれのテーブルに挿入する方法について問題点を解説します。
  • データの不具合時に片方のテーブルにのみ登録される可能性がある問題を回避する方法を考えます。
回答を見る
  • ベストアンサー

別々のテーブルで共通のid使う

一つのページから別々のテーブルにデータをINSERTしたいのですが、"id"と"number"は同じ値でそれぞれのテーブルにいれたいのですが、どうやってやるのでしょうか? 下のPHPのコード(一部)でデータを流してみたのですが、このままやると、もしデータに不具合があって片方だけ登録されないことがあると、一方は登録されて、一方は登録されないという事態が発生してしまい、"id"が違う番号で登録されてしまう可能性があります。 id int(8) NOT NULL AUTO_INCREMENT で"id"は作りました! $insertSQL1 = sprintf("INSERT INTO tbl1 (id, number, name, price) VALUES (%s, %s, %s, %s)", GetSQLValueString($_POST['id'], "int"), GetSQLValueString($_POST['number'], "text"), GetSQLValueString($_POST['name'], "text"), GetSQLValueString($_POST['price'], "int")); $insertSQL2 = sprintf("INSERT INTO tbl2 (id, number, ename, eprice, extra) VALUES (%s, %s, %s, %s, %s)", GetSQLValueString($_POST['id'], "int"), GetSQLValueString($_POST['number'], "text"), GetSQLValueString($_POST['ename'], "text"), GetSQLValueString($_POST['eprice'], "int"), GetSQLValueString($_POST['extra'], "text")); 別々のテーブルで共通のidを使う方法はないでしょうか? phpMyAdminのSQLを使ってます。 回答よろしくおねがいします!

  • MySQL
  • 回答数4
  • ありがとう数12

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

  • ベストアンサー
  • mpro-gram
  • ベストアンサー率74% (170/228)
回答No.4

共通id にauto_increment値は使わない意見に賛成。 その場合でも、トランザクションにしないと、片方のテーブルにのみ挿入できてもう一方は挿入されない事態は発生する。 mysql_(iが付かない)関数群はトランザクション機能の無かった時代の遺物なので(トランザクションもトリガーも未対応)、 mysqliクラスかPDOクラス群を使って下さい。 あと、mysql サーバーのversion が5.1 以降であることと、テーブル作成時に innodb エンジンを指定している必要があります。

soccerrlove
質問者

お礼

PDOクラスってものがあるんですね!知りませんでした! まだまだ知らないことが多そうなのでもっと勉強します! 回答ありがとうございました!

その他の回答 (3)

  • maiko0318
  • ベストアンサー率21% (1483/6970)
回答No.3

>調べてたら、Commitにあたる部分はあったのですが、autocommitの方が見つからなかったのです。 当方、Mysqlは知りませんので、お力になれません。すいません。

soccerrlove
質問者

お礼

いえいえ、とてもためになりました! 回答ありがとうございます!

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

考え方が間違っています >id int(8) NOT NULL AUTO_INCREMENT オートインクリメントでつくるidを連携用のIDに利用するのは あまり頭のいいやり方ではありません。 オートインクリメントでつくったプライマリーキー(?)はあくまで レコードを特定するためのキーにしか(保障がないという意味で)利用できません 任意のルールできちんと生成したIDを元に処理するようにしてください もしくはなんらかのトリガーを利用して、別テーブルにデータを吐き出す ような仕組みにすればよいでしょう

soccerrlove
質問者

お礼

なるほど! そういう考え方もあるんですね! 回答ありがとうございます!

  • maiko0318
  • ベストアンサー率21% (1483/6970)
回答No.1

>一方は登録されて、一方は登録されないという事態が発生してしまい この事態を防ぐために「トランザクション」という考え方があります。 insert insert insert のあとにcommitすればテーブルが更新されます。 逆にrollbackすればテーブルの更新はありません。 commit,rollbackの処理でエラーが生じることはありません。 もしあるとすればデータベースのシステムが壊れています。

soccerrlove
質問者

お礼

回答ありがとうございます!

soccerrlove
質問者

補足

回答ありがとうございます! mysqli_autocommit($link, FALSE); mysqli_commit($link) を使ってみたのですが、普段使ってるのが mysql_select_db($database, $link); のようなmysqlのあとに"i"がない形なのですが、 調べてたら、Commitにあたる部分はあったのですが、autocommitの方が見つからなかったのです。 これに対する解決策があったら教えてくれるとありがたいです。 よろしくおねがいします!

関連するQ&A

  • htmlspecialcharsについて(セキュリティ)

    PHP5&MySQL5(OS:XP)で、テキストボックスに文字をいれ、DBに書き込む処理を作成しています。 「htmlspecialchars」を利用してセキュリティをかけたいのですが、htmlspecialcharsを使っても使わなくても同じ結果(セキュリティがきかない)が出てきてしまいます。 何が理由がお分かりの方、教えていただけると助かります。 ---ソース if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "formComment")) { $insertSQL = sprintf("INSERT INTO comment_table (entry_id, name, email, url, `comment`) VALUES (%s, %s, %s, %s, %s)", GetSQLValueString($_POST['entry_id'], "int"), GetSQLValueString($_POST['name'], "text"), GetSQLValueString($_POST['email'], "text"), GetSQLValueString($_POST['url'], "text"), GetSQLValueString($_POST['comment'], "text")); を if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "formComment")) { $insertSQL = sprintf("INSERT INTO comment_table (entry_id, name, email, url, `comment`) VALUES (%s, %s, %s, %s, %s)", GetSQLValueString(htmlspecialchars($_POST['entry_id']), "int"), GetSQLValueString(htmlspecialchars($_POST['name']), "text"), GetSQLValueString(htmlspecialchars($_POST['email']), "text"), GetSQLValueString(htmlspecialchars($_POST['url']), "text"), GetSQLValueString(htmlspecialchars($_POST['comment']), "text")); に変えています。 また、$_POST['comment']の入力文字は、 <script type="text/Javascript">window.alert('Javascriptが実行されました');</script> でも <iframe width="500" height="250" src="http://book.xxxx.co.jp/"></iframe> でもタグの内容通りの結果が表示されてしまいます。

    • ベストアンサー
    • PHP
  • 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
  • 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
  • 複数テーブルで ID の一意性を保つ

    Debian GNU/Linux 3.1 で psql 8.1.2 を使用しています。 下記の要領でテーブルを作成し、2つのテーブルでIDが重ならないようにしようと意図しました。 CREATE TABLE t1 ( t1_id int2 UNIQUE NOT NULL, t1_name text NOT NULL ); NOTICE: CREATE TABLE / UNIQUE will create implicit index "t1_t1_id_key" for table "t1" CREATE TABLE CREATE TABLE t2 ( t2_id int2 UNIQUE NOT NULL, t2_name text NOT NULL ); NOTICE: CREATE TABLE / UNIQUE will create implicit index "t2_t2_id_key" for table "t2" CREATE TABLE CREATE FUNCTION unique_t12_id(int2) RETURNS BOOLEAN AS 'SELECT NOT ( EXISTS(SELECT * FROM t1 WHERE t1_id = $1) AND EXISTS(SELECT * FROM t2 WHERE t2_id = $1) );' LANGUAGE SQL; CREATE FUNCTION ALTER TABLE t1 ADD CONSTRAINT con_unique_t12 CHECK (unique_t12_id(t1_id)); ALTER TABLE ALTER TABLE t2 ADD CONSTRAINT con_unique_t12 CHECK (unique_t12_id(t2_id)); ALTER TABLE ところが実際は上手くいきませんでした。 INSERT INTO t1 VALUES(1, 'test1'); INSERT 0 1 INSERT INTO t2 VALUES(2, 'test2'); INSERT 0 1 INSERT INTO t2 VALUES(2, 'test3'); ERROR: duplicate key violates unique constraint "t2_t2_id_key" # ここまでは期待通りの挙動です INSERT INTO t2 VALUES(1, 'test4'); INSERT 0 1 ここで制約が働いて欲しかったのですが、素通りでINSERTされています。 下記のように、操作後の関数の戻り値は「偽」なのでこの操作は制約に引っかかると思うのですが 何故意図したように動かないのでしょうか。 SELECT *,unique_t12_id(t2_id) FROM t2; t2_id | t2_name | unique_t12_id -------+---------+--------------- 2 | test2 | t 1 | test4 | f (2 rows) スペースが詰まって読みづらい箇所もありますが、よろしくお願いします。

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

    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つの関連するテーブルの並び替え

    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
  • 別テーブルから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
  • int型フィールドにnullを登録できない・・・

    > insert into tbl_tst values (001,'',21000,,22,4400,'3~4日','∞') とすると syntax error になってしまいます。 > insert into tbl_tst values (001,'',21000,'',22,4400,'3~4日','∞') とすると out of range になってしまいます。 > insert into tbl_tst values (001,'',21000,0,22,4400,'3~4日','∞') は通常に登録できます。 > insert into tbl_tst values (001,'',21000,'0',22,4400,'3~4日','∞') も通常に登録できます。 4カラム目のフィールドなのですが、show fields で見ても int(11) Null→YES  Default→NULLとなっております。 NULLを登録(何も値を入れない)したいのですが、 どうすればよいでしょうか。 ご存知の方いらっしゃいましたらご教示願います。 宜しくお願い致します。

    • ベストアンサー
    • MySQL
  • 異なる2つのテーブルからIDを抜き出し併記したい

    地域別職業別電話帳を作っています。 テーブルは下記の3つです。 市町村テーブル 01city(a1 INT NOT NULL PRIMARY KEY,a2_pre_id INT,a3_pre_name TEXT,a4_city_id INT,a5_city_name TEXT,a6_city_name_kana TEXT); 職業テーブル 03works(c1 INT NOT NULL PRIMARY KEY,c2_work TEXT,c3_aiu TEXT,c4_aiu_id INT); 会社名テーブル tokyo(company TEXT NOT NULL,zip TEXT,address TEXT,tel text,fax TEXT,freedial TEXT,industryA TEXT,hp TEXT,mail TEXT,comment1 TEXT,coid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,industry1 TEXT,zip_id INT,pre_name TEXT,city_name TEXT,induid INT,cityid INT); 会社名の表示については下記のような表示により、13101(千代田区)の104(ラーメン)屋リストを表示出来るようには設定しました。 (クエリー表示を /13101/104/ で表示出来るように .htaccess で指定しています。) http://127.0.0.1/ccs/result/13101/104/ 次に、これを指定するためには、ユーザーが、千代田区(13101) ラーメン(104) と指定したら、http://127.0.0.1/ccs/result/13101/104/のURLが表示出来ることにすれば完成となりますが、ここで躓いてしまいました。 千代田区の職業別一覧なら SELECT * FROM `01city` WHERE a4_city_id = 13101" で表示可能です。 東京のラーメン屋だけなら、 SELECT * FROM `03works` WHERE c1 = 104" で表示な可能です。 しかし、千代田区のラーメン屋になると、拾ってくるID(a4_city_id、c1)のテーブルがそれぞれ別のテーブル(01city、03works)のため、http://127.0.0.1/ccs/result/13101/104/のように並べて表示させることができません。 join関数は、2つのテーブルにキーとなる同じデータがあって初めて結合が可能ですが、今回の場合は、キーとなる同じデータがありません。 普通にありそうな例なのですが、どうすれば可能でしょうか? 基礎的な部分なのかもしれませんが、どうぞ宜しくお願い致します。

    • ベストアンサー
    • MySQL
  • 閉包テーブルのノードの移行について

    このジャンルでお願いします。 次のようなテーブルで CREATE TABLE IF NOT EXISTS item ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(32) NOT NULL, PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO item (name) VALUES ('item1'); INSERT INTO item (name) VALUES ('item2'); INSERT INTO item (name) VALUES ('item3'); INSERT INTO item (name) VALUES ('item4'); INSERT INTO item (name) VALUES ('item5'); INSERT INTO item (name) VALUES ('item6'); CREATE TABLE IF NOT EXISTS treepath ( ancestor_id int(11) NOT NULL, descendant_id int(11) NOT NULL, FOREIGN KEY (ancestor_id) REFERENCES item(id) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (descendant_id) REFERENCES item(id) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY(ancestor_id, descendant_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO treepath (ancestor_id, descendant_id) VALUES (1, 1); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (1, 2); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (1, 3); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (1, 4); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (1, 5); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (1, 6); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (2, 2); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (2, 4); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (2, 5); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (2, 6); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (3, 3); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (4, 4); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (4, 6); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (5, 5); INSERT INTO treepath (ancestor_id, descendant_id) VALUES (6, 6); item1┬item2    │ ├item4    │ │  └item6    │ └item5    │    └item3 を item1┬item2    │ │      │ └item5    │    └item3      └item4        └item6 のようにitem4以下のノードをitem3の下に移したいのですが、 その場合のtreepathテーブルの更新はどのようなSQL文にすれば良いのでしょうか?

    • ベストアンサー
    • MySQL