みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

前のidをコピーするSQL文

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>

投稿日時 - 2015-01-14 20:59:35

QNo.8891586

困ってます

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

>配列で扱わなければならないのに文字列で扱っていることがエラーの原因なのでしょうか
>$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

投稿日時 - 2015-01-16 21:01:18

お礼

ありがとうございます!
アドバイス通りに入力したところ、私の求めていた動作をしてくれました!
違う方向で考えていていくら調べても答えが出てこないので本当に助かりました。
普通にPHPを扱うのであればもっと配列について基本を身に着けないと難しいですね。
基本は目を通しているつもりでもいざ、自分で開発となるとやはり抜けてしまっているんだと実感して
しまいます。教本通りとか作るだけでは身につかないですね。

PHPの配列に関するサイトと別の直近idについても丁寧に教えてくださり本当にありがとうございます!

投稿日時 - 2015-01-16 22:23:53

ANo.3

このQ&Aは役に立ちましたか?

16人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.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);

投稿日時 - 2015-01-16 21:26:56

お礼

>自動生成したIDで別のテーブルと連携するといろいろデータに不整合が
>起こりそうな気がしますが・・・

ご指摘ありがとうございます!
正直私も思いつきなので仕組みとして合っているのかどうなのかはわからないです。

複数テーブルを管理画面から入力フォームで扱う場合に1つのテーブルのユニークなid
を基点にそのidをコピーして別のテーブルにそのidの番号を入れなければブラウザからSELECTして同時に表示するときに
上手く表示できないのではと思い考えてみました。

yamabejp様に整合性をつっこまれてしまうと本当に大丈夫なのか心配になってしまいますが、自分で作っているだけなので
まあいいかなと思っております。

そしてトリガーの仕組みをご教授いただきありがとうございます!
トリガーに関しては基礎の本を少し読んだことがあるだけなのですぐに扱うのは私には難しいので少し時間がかかるかもしれません。
来週中には試してみたいと思っております!

投稿日時 - 2015-01-16 23:04:56

ANo.2

状況的に

INSERT INTO players
する際に、オートインクリメントのプライマリーキーか何かを発行して

INSERT INTO team
するときにリレーション用のキーとして使いたいということでしょうか?

そのわりにplayersのIDがteamのチームIDとしてインサートするのは
いまいち道理があわないような・・・

なおplayersにインサートするたびにteamへのインサートが必ず発生するのであれば
トリガーで処理してもよいかもしれません。

投稿日時 - 2015-01-15 11:54:00

補足

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を使う場合、中々ネット上に情報が無いので苦戦しそうです。
必要であれば考えてみたいと思っております。

もし気が向きましたらまたアドバイス頂けたらと思っております。
今回もありがとうございました。

投稿日時 - 2015-01-16 17:17:14

ANo.1

2回目で挿入しようとしてる $last_id は配列では?
開発中は error_reporting(E_ALL);にしておくとよいかと。

投稿日時 - 2015-01-15 11:06:59

補足

いつもアドバイスいただき誠にありがとうございます。
ご指摘通り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) }



もしよろしければまたご教授していただきたいと思っております。

投稿日時 - 2015-01-16 15:12:34

お礼

ベストアンサーはいつもお世話になっているお二方なので大変難しい選択なのですが、今回はわかりやすかったということ
配列に関するわかりやすいサイトと別の直近idの取得方法も教えてくださったので
JaneDue様をベストアンサーとさせて頂きました。
あと理由としてはトリガーの機能も使い勝手がまだ少ししか理解してないと言うこともあります。
本当に申し訳ありません。でもおかげ様で調べるきっかけは出来たので大変感謝しております。ありがとうございます!
トリガーの基本はなんとなく理解できたような気がします。
PDOを利用するプログラムを入力するのではなくMySQLに直接設定するということをやっと理解できました。
またMySQLのトリガーについての書籍やホームページなど読み漁りたいと思っております。
今回の質問に関しては私の考えたロジックが微妙なのである程度期間が経過したら閉じようと思っております。
今回もお二方に素晴らしいアドバイスいただき本当に感謝しております。
誠にありがとうございました!

投稿日時 - 2015-01-22 01:02:32

あなたにオススメの質問