
MySQLを使って管理画面を作っております。
$sql='INSERT INTO players(name,price,position_id) VALUES(?,?,?)';
という文で使ったidをコピーしてから次のINSERTの文でそのidの番号を使って別テーブルのカラムにその番号をINSERTするしくみを作りたいのですがなかなか上手くいきません。
var_dump($last_id);では番号がコピーされているのですが、INSERTができません。
いつもお世話になってしまい大変恐縮なのですが、どなたかご教授いただけないでしょうか?よろしくお願い致します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="../../xxxxx/team.css"/>
<title>選手追加完了</title>
</head>
<body>
<div id="main">
<?php
$pro_name=$_POST['name'];
$pro_price=$_POST['price'];
$pro_position_id=$_POST['position_id'];
$pro_team=$_POST['team_name'];
$pro_name=htmlspecialchars($pro_name);
$pro_price=htmlspecialchars($pro_price);
$pro_position_id=htmlspecialchars($pro_position_id);
$pro_team=htmlspecialchars($pro_team);
$dns = "mysql:host=localhost; dbname=player;charset=utf8";
$dns_id = "xxxxx";
$dns_pw = "xxxxxxx";
try
{
$conn = new PDO($dns, $dns_id, $dns_pw, array(PDO::ATTR_EMULATE_PREPARES => false));
} catch (Exception $e) {
echo 'ERROR: ' . $e->getMessage();
die();
}
try {
//トランザクションを開始する。オートコミットがオフになる
$conn->beginTransaction();
//処理その(1)
$sql='INSERT INTO players(name,price,position_id) VALUES(?,?,?)';
$stmt=$conn->prepare($sql);
$data[]=$pro_name;
$data[]=$pro_price;
$data[]=$pro_position_id;
$stmt->execute($data);
//直近id取得
$last_id_sql = "SELECT LAST_INSERT_ID() as id";
$stmt = $conn->prepare($last_id_sql);
$stmt->execute();
$last_id = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt->closeCursor();
//確認var_dump($last_id);
//処理その(2)
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql2='INSERT INTO team(team_id,team_name) VALUES(?,?)';
$stmt=$conn->prepare($sql2);
$data2[]=$pro_team;
$data2[]=$last_id;
$stmt->execute(array($last_id,$pro_team));
$stmt->closeCursor();
//確認var_dump($last_id);
//変更をコミットする
$conn->commit();
} catch(PDOException $e){
//変更をロールバックする
$conn->rollBack();
echo 'ERROR:' . $e->getMessage();
}
// 切断
$conn = null;
print $pro_name;
print'を追加しました。<br />';
?>
<a href="xxxxx">戻る</a>
</div><!--main-->
</body>
</html>
No.3ベストアンサー
- 回答日時:
>配列で扱わなければならないのに文字列で扱っていることがエラーの原因なのでしょうか
>$last_idのところを配列に直せば良いのでしょうか?
その逆で「文字列を入れるべきところに、配列を充てているので『型変換が発生してますよ』」ということです。$last_id['id'] で取得できるので
$stmt->execute(array($last_id['id'],$pro_team));
でよいのでは?
配列については以下が分かりやすいかも。
http://www.phpbook.jp/tutorial/array/
※直近idの取得には
$newID =$conn->lastInsertId();
という関数もあります。御参考まで
http://php.net/manual/ja/pdo.lastinsertid.php
ありがとうございます!
アドバイス通りに入力したところ、私の求めていた動作をしてくれました!
違う方向で考えていていくら調べても答えが出てこないので本当に助かりました。
普通にPHPを扱うのであればもっと配列について基本を身に着けないと難しいですね。
基本は目を通しているつもりでもいざ、自分で開発となるとやはり抜けてしまっているんだと実感して
しまいます。教本通りとか作るだけでは身につかないですね。
PHPの配列に関するサイトと別の直近idについても丁寧に教えてくださり本当にありがとうございます!
No.4
- 回答日時:
自動生成したIDで別のテーブルと連携するといろいろデータに不整合が
起こりそうな気がしますが・・・
無理やりやろうと思えば以下参考にしてみてください
//テーブル作成
create table players(id int not null auto_increment primary key,name varchar(100),price int,position_id int);
create table team(id int not null primary key,team_name varchar(100));
※仕様
playersテーブルに挿入した際発行されるidをteamのプライマリキーとして
データを挿入する。
ただしplayersテーブルのデータを削除したり、抜け番をうめたり特殊なことは
一切無視
//トリガー作成
DROP TRIGGER IF EXISTS players_to_team;
DELIMITER //
CREATE TRIGGER players_to_team AFTER INSERT ON players
FOR EACH ROW BEGIN
INSERT IGNORE INTO team SET id= NEW.id,team_name=@team_name;
END;
//
DELIMITER ;
//playersにデータを挿入する(ただしteamの名前は別途変数で指定)
insert into players (id,name,price,position_id) values((select @team_name:='t1'),'p1',100,1);
insert into players (id,name,price,position_id) values((select @team_name:='t2'),'p2',200,0);
insert into players (id,name,price,position_id) values((select @team_name:='t3'),'p3',400,1);
insert into players (id,name,price,position_id) values((select @team_name:='t4'),'p4',800,0);
//確認
select * from players inner join team using(id);
>自動生成したIDで別のテーブルと連携するといろいろデータに不整合が
>起こりそうな気がしますが・・・
ご指摘ありがとうございます!
正直私も思いつきなので仕組みとして合っているのかどうなのかはわからないです。
複数テーブルを管理画面から入力フォームで扱う場合に1つのテーブルのユニークなid
を基点にそのidをコピーして別のテーブルにそのidの番号を入れなければブラウザからSELECTして同時に表示するときに
上手く表示できないのではと思い考えてみました。
yamabejp様に整合性をつっこまれてしまうと本当に大丈夫なのか心配になってしまいますが、自分で作っているだけなので
まあいいかなと思っております。
そしてトリガーの仕組みをご教授いただきありがとうございます!
トリガーに関しては基礎の本を少し読んだことがあるだけなのですぐに扱うのは私には難しいので少し時間がかかるかもしれません。
来週中には試してみたいと思っております!
No.2
- 回答日時:
状況的に
INSERT INTO players
する際に、オートインクリメントのプライマリーキーか何かを発行して
INSERT INTO team
するときにリレーション用のキーとして使いたいということでしょうか?
そのわりにplayersのIDがteamのチームIDとしてインサートするのは
いまいち道理があわないような・・・
なおplayersにインサートするたびにteamへのインサートが必ず発生するのであれば
トリガーで処理してもよいかもしれません。
この回答への補足
yambejp様、いつもご助力いただき本当にありがとうございます。
>INSERT INTO players
>する際に、オートインクリメントのプライマリーキーか何かを発行して
>INSERT INTO team
>するときにリレーション用のキーとして使いたいということでしょうか?
formから同じ番号を2回入力するのは煩わしいかと思いplayersとteamというテーブルに関連を持たせて1回の入力でINSERT出来たほうが良いのかなと思い、こういった仕組みを作ってみようと思いました。
あとでSELECTする場合2つのテーブルを一緒に表示したいということも考えたらIDで
関連付けしようということになりました。
playersのIDはプライマリーキーでteamのteam_idのカラムはユニークではないということに
すれば仕組みとしてはセーフかと思ったのですが、その辺りの考えが違うのでしょうか?
そうではなく1つのテーブルにまとめたほうが良いのでしょうか?
あえて2つのテーブルのINSERTを考えてみたいのですが。。
>なおplayersにインサートするたびにteamへのインサートが必ず発生するのであれば
>トリガーで処理してもよいかもしれません。
トリガーの処理はPDOを使う場合、中々ネット上に情報が無いので苦戦しそうです。
必要であれば考えてみたいと思っております。
もし気が向きましたらまたアドバイス頂けたらと思っております。
今回もありがとうございました。
No.1
- 回答日時:
2回目で挿入しようとしてる $last_id は配列では?
開発中は error_reporting(E_ALL);にしておくとよいかと。
この回答への補足
いつもアドバイスいただき誠にありがとうございます。
ご指摘通りerror_reporting(E_ALL);といれたところ、
Notice: Array to string conversion in というerrorが出ました。
ということは配列で扱わなければならないのに文字列で扱っていることがエラーの原因なのでしょうか?
$data2[]=$last_id;
$stmt->execute(array($last_id,$pro_team));
上記の部分を直せばいいのかと思い、いろいろ調べたのですが恥ずかしながらわかりませんでした。
$last_idのところを配列に直せば良いのでしょうか?
var_dump($last_id);で出る内容は以下のようになります。
array(1) { ["id"]=> int(265) }
もしよろしければまたご教授していただきたいと思っております。
ベストアンサーはいつもお世話になっているお二方なので大変難しい選択なのですが、今回はわかりやすかったということ
配列に関するわかりやすいサイトと別の直近idの取得方法も教えてくださったので
JaneDue様をベストアンサーとさせて頂きました。
あと理由としてはトリガーの機能も使い勝手がまだ少ししか理解してないと言うこともあります。
本当に申し訳ありません。でもおかげ様で調べるきっかけは出来たので大変感謝しております。ありがとうございます!
トリガーの基本はなんとなく理解できたような気がします。
PDOを利用するプログラムを入力するのではなくMySQLに直接設定するということをやっと理解できました。
またMySQLのトリガーについての書籍やホームページなど読み漁りたいと思っております。
今回の質問に関しては私の考えたロジックが微妙なのである程度期間が経過したら閉じようと思っております。
今回もお二方に素晴らしいアドバイスいただき本当に感謝しております。
誠にありがとうございました!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルで最後の文字だけ置き...
-
マイクラPC版のコマンドで効率...
-
少し前に放送されていたオムツ...
-
エクセルの関数について教えて...
-
Access パラメータクエリをcsv...
-
VBA リボンのCheckBox2個をOpt...
-
WordpressのContact form 7でzi...
-
Excel2000でレーダーチャートの...
-
レコード数が増えすぎた場合の対処
-
DMAXを使って登録ボタンを作りたい
-
SQLについての質問
-
【MySQL】auto_incrementの値を...
-
VMwareがCDドライブを認識する...
-
Excel再起動でアドインのタブが...
-
Outlook 送受信エラー
-
木偏に「久」
-
英語ができる方、問題をお願い...
-
過剰なオブジェクト指向脳から...
-
フィルターかけた後、重複を除...
-
1、Rstudioで回帰直線を求める...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで最後の文字だけ置き...
-
エクセルの関数について教えて...
-
VIEWの元のテーブルのindexって...
-
エラー 1068 (42000): 複数の主...
-
SQLサーバから、項目の属性(型...
-
select文のwhere句に配列を入れ...
-
SQL Left Join で重複を排除す...
-
Access パラメータクエリをcsv...
-
マイクラPC版のコマンドで効率...
-
【Transact-sql】 execの結果を...
-
sqlで、600行あるテーブルを100...
-
SQLにて特定の文字を除いた検索...
-
1テーブル&複数レコードの更新...
-
PL/SQLの変数について
-
WordpressのContact form 7でzi...
-
複数テーブルのGROUP BY の使い...
-
バインド変数について
-
inner joinをすると数がおかし...
-
MySQLのint型で001と表示する方...
-
updateを1行ずつ実行したい。
おすすめ情報