質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

5回答

4434閲覧

中間テーブルへのデータ登録

takeke

総合スコア60

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2018/10/18 09:34

編集2022/01/12 10:55

スケジューラーを作っています。
PHPのMYSQLにデータ登録の質問なのですが、user,schedule,user_scheduleとテーブルが3つあって、user_scheduleというは中間テーブルになりまして、持っているカラムはuser_schedule_id,user_id,schedule_idになります。

ここでscheduleをフォームから登録すると同時にuser_scheduleのschedule_idにも登録したいのですが、どのようにコードを組み上げるのかがイメージがつきません、

schedule_idというのは自動付番なので、一度scheduleが登録されないと存在しないので、中間テーブルであるuser_scheduleにはどうやって登録したらいいものかと、、、

登録の流れは、userが複数いて、scheduleを登録する際に、scheduleテーブルの項目と、そのスケジュールに参加するuserも一緒に登録する流れです。

scheduleテーブルにはカラムとしてuser関連のものは持っていないので、user_scheduleテーブルが1つのschedule_idと1つOR複数のuser_idを持ちます。

やってみたことは、insertして、excuteしてからまたinsertみたいなことや、最初のinsertの時にjoinでuser_schedule,scheduleを結合くらいはしましたがやはりうまくいきませんでした。

ひとまず今現在のエラーです。

Fatal error: Uncaught Error: Call to undefined method PDOStatement::excute() in C:\xampp\htdocs\scd\php\top.php:29 Stack trace: #0 {main} thrown in C:\xampp\htdocs\scd\php\top.php on line 29

php

1 $pdo = db_connect(); 2 $stmt = $pdo->prepare('INSERT INTO schedule(start_date,end_date,start_time,end_time,plan_category,plan_title,plan_detail,place,pab_flag) VALUES (?,?,?,?,?,?,?,?,?)'); 3 $stmt->execute([$start_date, $end_date, $start_time, $end_time, $plan_category, $plan_title, $plan_detail, $place, $pab_flag]); 4 $last_s_id = 'SELECT LAST_INSERT_ID()'; 5 $stmt = $pdo->prepare('INSERT INTO user_schedule(schedule_id) VALUES $last_s_id'); 6 $stmt->excute(); 7

アドバイス等よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/10/18 10:54 編集

「うまくいかない」だけでは何を元に何が起きてるのか誰にもわかりませんよ。提示できる情報はなるべく全て提示してください
takeke

2018/10/18 11:28

ご指摘ありがとうございます。色々試した後だったので今までのエラーの詳細を現在の質問分以上にうまく説明できないので省かせていただきましたm(_ _)m
m.ts10806

2018/10/18 12:12

コードとエラーメッセージを提示すればそこまで説明する必要はないかと思いますが。下手に文章で説明するより(できていない)コードをだしたほうが伝わります。
m.ts10806

2018/10/18 12:15

逆に質問者の自己判断で本来回答に必要であるはずの情報を削ってしまうほうが問題解決の観点から致命的です。初めて使うタクシーで何の具体的な説明もなく目的地には着けませんが、下手に道順を口頭で説明するより地図を見せたりしたほうが早かったりしますよね。
m.ts10806

2018/10/18 12:31

PHPの文法ミスですが、そこはなぜそういうエラーになっているかわかりますか?おそらく要件以前の問題になってます。
takeke

2018/10/18 12:43

文法が違うのはわかっていましたが、未だ改善方法がわかっていません。エラー文は調べました
takeke

2018/10/18 12:57

状況が変わったので修正しました。
m.ts10806

2018/10/18 12:57

excute ←スペルミス。エラー文読みましょう。
takeke

2018/10/18 13:20

単純なミスすみません><一旦scheduleテーブルをexecuteしてからselectしてuser_scheduleにinsertしてまたexecuteの流れではありますよね?
m.ts10806

2018/10/18 13:23

先走りすぎです。1行きちんと通ってから次にいってください。デバッグ(debug)で確実にできていることが確認できていない段階で次々いくものではありません。先走りは問題解決を遅らせるだけです。
takeke

2018/10/18 13:38

わかりました><とりあえず中途半端なまま置いておいてデバックの記事読んで導入に取り組んでみますm(_ _)m
guest

回答5

0

php

1 $pdo = db_connect(); 2 $stmt = $pdo->prepare('INSERT INTO schedule(start_date,end_date,start_time,end_time,plan_category,plan_title,plan_detail,place,pab_flag) VALUES (?,?,?,?,?,?,?,?,?)'); 3 $last_s_id = 'SELECT LAST_INSERT_ID()'; 4//↑いきなりSELECT文作っているけどこれだと文字列だけで何も実行していないから実際は SELECT LAST_INSERT_ID() という文字列が入っただけの変数 5 $stmt = $pdo->prepare('INSERT INTO user_schedule(schedule_id) VALUES $last_s_id'); 6//↑シングルクォートの中に普通に変数入れて展開できたっけ? 7//ただ、正しく変数展開できても「 INSERT INTO user_schedule(schedule_id) VALUES SELECT LAST_INSERT_ID() 」というSQLになるけど、これ、ちゃんと実行できるSQL? 8//いずれにしてもVALUESの節としてはSQL的に正しくない文法 9 $stmt->execute([$start_date, $end_date, $start_time, $end_time, $plan_category, $plan_title, $plan_detail, $place, $pab_flag]); 10//↑execute()はいいのだけど、$stmtには直前のprepare()の結果が入ってるから、引数の数とプリペアドステートメントの数合ってません。というか?が1つもないSQLに対して何個も引数を渡している形。 11 12//というか違うステートメントなら同じ変数名にしないほうがいい。$stmtはあくまで任意の名前。なんのステートメントなのかわかりやすい名前つけておいたほうが後々見た時に何やってるかわかる。

変数作るたびにvar_dump()で都度状況確認すればわかることも多いはず。
デバッグ覚えましょう。

投稿2018/10/18 12:55

編集2018/10/18 12:59
m.ts10806

総合スコア80765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takeke

2018/10/18 13:16

ありがとうございます>< $last_s_id = 'SELECT LAST_INSERT_ID()'; これは $last_s_id = $pdo->prepare( 'SELECT LAST_INSERT_ID()');になるということでしょうか? デバックも必要ですね。確認するまでの工程が多くて現在やりづらいです。余裕できたらデバック導入できるようにしてみます。
m.ts10806

2018/10/18 13:21

逆です。デバッグしないから余裕ができないんですよ。 デバッグはHelloWorldの次に覚えるべきものといっても過言ではありません。 デバッグをしないことは問題解決を放棄しているのと同義です。 > $last_s_id = 'SELECT LAST_INSERT_ID()'; これは $last_s_id = $pdo->prepare( 'SELECT LAST_INSERT_ID()');になるということでしょうか? 私の回答はどのように書いてますか? コメント読みづらいならそう言ってもらいたいのですが。。 だからデバッグしてくださいと言ったんですけど。 変数作るたび、何か入れるたびに直後にvar_dump()入れて確認したらいいだけです。
takeke

2018/10/18 13:32

すみません、デバッグするのにまた躓くと思いますが先程の記事読んで導入してみます。 $last_s_id = 'SELECT LAST_INSERT_ID()'; //↑いきなりSELECT文作っているけどこれだと文字列だけで何も実行していないから実際は SELECT LAST_INSERT_ID() という文字列が入っただけの変数 ということで考えた末でした。その後の INSERT INTO user_schedule(schedule_id) VALUES SELECT LAST_INSERT_ID()というのが正しくないということも加味した素人考えでしたようですすみません><
m.ts10806

2018/10/18 18:49

回答にリンク貼っておいたのですがどこがわからなかったんでしょうか。 それとも「デバッグとはそもそもなにか」というところも分かっていないということでしょうか(まあプログラミング言語ほぼ全てにある概念なので調べれば一発ですけど) 厳しいこというようですがデバッグで躓いてたらそれはhello worldで躓くのと同等です。それくらいなんてこともないことです。 もちろん適切なデバッグができるかどうかは流れとかロジックを読む力は必要ですけど、導入などと大袈裟なものではありません。 本番ソースには不要な記述ですし
takeke

2018/10/19 06:15

活用の仕方とかがまだよくわかってません。デバッグはエラーを見つけて修正することと認識しています。 現在はxdebugを導入しました。VSCodeを使っているのですが、まだそちらでもXdebugの使い方がよ変数調べるくらいしかわかりませんでした。普通に、phpの記述の中にvar_dump($変数);でやるくらいしかわからなかったので、今のところ全てのページにvar_dump($変数);で変数に$_POSTと$_GETと$_SESSION入れて、現在のページにこの変数がきていてるのを確認することはできるようにはなりました。
m.ts10806

2018/10/19 06:33

>phpの記述の中にvar_dump($変数);でやるくらいしかわからなかったので、 それ知っててやってるなら私の回答はなくてもよかったはずですね。
takeke

2018/10/19 06:49

ありがとうございます。 いえ、mts10806さんの回答のリンクを読んだ上で理解できた範囲の話になります。
m.ts10806

2018/10/19 07:05

失礼。勘違いしてました。
退会済みユーザー

退会済みユーザー

2018/10/19 08:30

デバッグ用の関数すすめるより、デバッグ環境作ることすすめたいなぁ(個人の感想)
m.ts10806

2018/10/19 09:17

まあ、初学者はまずはvar_dumpからと。
guest

0

SELECT LAST_INSERT_ID();で直前にAUTO_INCREMENTされたidが取得できますので、その値をuser_scheduleテーブルにinsertで入れてあげてください。

投稿2018/10/18 09:46

colling

総合スコア798

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

  1. scheduleを登録
  2. lasrinsertid()で今登録したscheduleのidを取得参考
  3. user_scheduleにsessionに持っているであろうuser_idと2で取得したschedule_idを登録

という感じで可能です。

投稿2018/10/18 09:45

tanat

総合スコア18709

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takeke

2018/10/18 11:21

ありがとうございます! user_id自体は登録行為をしているuserが絶対そのスケジュールをするとは限らないのでuserを一覧でだして、その中の任意のuserをschedule_idと一緒にuser_scheduleに登録したいのでsessionのところだけ省く形になりそうですね!
tanat

2018/10/18 11:26

はい、その通りです。
guest

0

「今作っている」ということなので設計面での回答をいたします。

scheduleテーブルにはカラムとしてuser関連のものは持っていないので、user_scheduleテーブルが1つのschedule_idと1つOR複数のuser_idを持ちます。

この構造は作ろうとしているものにとって適切なかたちなのでしょうか?

  • scheduleテーブルにownerを持つことはしないのでしょうか?

ユーザのいないスケジュールは禁止しそうな雰囲気を感じたのですが、参加者を複数削除する操作を今後作ったとき、ユーザが0人になった場合を検知し、またそれを利用者にうまく応答する動作のイメージはついていますか?

  • 参加者を増やす方法

参加者を後から増やすことは想定しておられるのでしょうか?だとすればそのとき、増やす先のスケジュールのidはどうやって求めるのでしょうか?
もし増やすことができるのであれば初回は「インサート→増やす先のスケジュールのidを取得→参加者を増やす(0から1に)」という処理と同じと考えられ、"最初だけidが分からなくて困る"というのは話として奇妙な気がします。逆に今ここで最初だけをピックアップしてそれにベストなコードを得てしまうと、参加者を増やすときに原理的に同じ問題に違うコードをあててしまう可能性があり、コードの設計としても良くないように思います。

  • user_scheduleテーブルは、どんな姿をしているのでしょうか?

user_scheduleはschedule_idとuser_idのペアをカラムとして持つテーブルだと思っていますが、上記の引用の後半を読むと、user_scheduleテーブルが、schedule_id, user_id1, user_id2, …といったカラムを持っている風にも受け取れます。もし後者のような姿なら、scheduleテーブルに持てるはずです。仮に前者のような姿なら、繰り返しになりますが2人を3人にするのも0人を1人にするのも同じことです。

データ構造上、ownerやscheduleテーブルにユーザ情報を持つことが妥当なら、scheduleのidが分からない、というのは悩む必要のない問題を悩んでいる可能性があります。

直接的な回答になっておらず申し訳ないのですが、プログラムを書いてから分かる問題もあるはずで、そういうときは本当にやりたいことに戻って見直すのも一つかと思います。

投稿2018/10/19 00:43

papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takeke

2018/10/19 07:05 編集

ありがとうございます! scheduleテーブル(以降s)、userテーブル(以降u)、user_scheduleテーブル(以降us)とさせていただきます。 ・sにはownerを持つことは今の所考えていません。uのいないsは削除すればいいだけかな?と考えていました。 ・参加者を増やす方法は、sの登録ページと、更新ページは別で用意するのでusにuを増減するだけかと考えていました。 ・usの姿ですが、us1つに対してsが1つでuが1or複数持つものと考えていました。 そもそもusというのは、uとsの情報をselectする際にusという両方のidだけ持つテーブルがあったほうがやりやすいと思ったので作りました。 改めて考えると構造的に不適切なのではないかと感じてきました。 追記です。やはり、usは1つにつき、s1つ、u1つというのがよさそうだと思うのでその方向で取り組もうと思います。
guest

0

ここでscheduleをフォームから登録すると同時にuser_scheduleのschedule_idにも登録したい

ちょっと意味不明
user_scheduleテーブル(以下us)はschedule(同s)テーブルとuser(同u)テーブルの
橋渡しですから、sにデータが登録されてもusには影響はありません
逆にsのデータが削除されたときはusに不整合が発生するので削除する必要はあるかもしれません。

まとめ

SQL

1create table user (uid int primary key,uval varchar(10)); 2 3create table schedule (sid int primary key auto_increment,sval varchar(10) unique key); 4 5create table schedule_user ( 6usid int primary key auto_increment, 7sid int not null , 8foreign key(sid) references schedule(sid) on delete cascade, 9uid int not null, 10foreign key(uid) references user(uid) on delete cascade, 11unique key us0(sid,uid)); 12
  • サンプルデータ

SQL

1insert into user values(101,'X'),(102,'Y'),(103,'Z'); 2insert into schedule(sval) values('A'),('B'),('C'); 3insert into schedule_user(sid,uid) values(1,101),(2,101),(1,102),(2,103),(3,102); 4
  • purocedure作成

SQL

1drop procedure if exists s2us_sval_uid; 2delimiter // 3create procedure s2us_sval_uid(in sval varchar(10),in uid int) 4begin 5start transaction; 6set @sval=sval,@uid=uid,@ucount=0; 7set @sql=concat("select count(*) into @ucount from user where `uid`=@uid"); 8prepare stmt from @sql; 9execute stmt; 10select @ucount; 11if @ucount>0 then 12insert ignore into schedule(`sval`) values(@sval); 13set @sql=concat("select sid into @sid from schedule where `sval`=@sval"); 14prepare stmt from @sql; 15execute stmt; 16insert ignore into schedule_user(`sid`,`uid`) values(@sid,@uid); 17end if ; 18commit; 19end 20// 21delimiter ; 22
  • 新規スケジュール"D"とuid:102を追加

SQL

1call s2us_sval_uid('D',102);

結果:sにDが追加され、usに4,102が追加

  • 既存スケジュール"D"とuid:103を追加

SQL

1call s2us_sval_uid('D',103);

結果:sには追加されないが、usに4,103が追加

  • 既存スケジュール"D"とusにすでに存在するuid:102を追加

SQL

1call s2us_sval_uid('D',102);

結果:sもusにも追加されない

  • その他

uidに存在しないデータを投入するときもsにはデータが投入されない

投稿2018/10/18 09:38

編集2018/10/19 02:35
yambejp

総合スコア114572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takeke

2018/10/18 09:44

かいとうありがとうございます!usにはそもそもinsertする必要がないということですか? イメージしていたのはusはs1つとuを1or複数持っているから、sを登録した時に一緒にusにもinsertしなきゃいけないのかなと思っていました
yambejp

2018/10/18 09:47

usにデータを登録する場合、sおよびu(user)にデータが存在しなければ追加する必要はありますが sに登録してもusに登録されることはないです
yambejp

2018/10/18 09:53

具体的に・・・ 仮にsにA,B,Cというタスクがあり、uにX,Y,Zのリソースがいたとして sとuには相関関係がないので当初usは空です その上で、XがA,B、YがA,C、ZがBのスケジュールを入れるとき usに(1,X,A),(2,B,X),(3,A,Y),(4,C,Y),(5,B,Z)を記載するわけです。 sにあらたにDというタスクが追加されても、その時点でDを利用するuはないので usにはデータを登録することはありません
takeke

2018/10/18 11:16

ありがとうございます>< 今考えているのが、sを登録する際に、sの情報だけでなく、一緒にそのsをするuも登録するような形にしようと考えています。なので、sが追加されると同時にusも追加されるものと考えていました。
yambejp

2018/10/18 11:42

なるほど、リソースが0のタスクは存在しないという定義なのであれば そういう運用もあるでしょう。 そうなるとsにinsertのトリガーを設定する必要がありますが、 その時点でリソースが確定していないので、usには新しいsidに対して uid=nullの仮データを投入することになるでしょう。 もしくはsvalとuidの組み合わせを指定すると svalからsidを作成してsidとuidの組み合わせでusに登録されるように プロシージャをつかって処理すればよいかもしれません
yambejp

2018/10/19 02:45

procedureのサンプルあげときました 参考までに
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問