環境:MySQL5.6.21,PHP5.6.2,Apache2.4,Windows8.0
下記サイトのようなプログラムを書き、
http://1811way.com/work008/sample002.txt
実行したところ
データを2度書いてしまいます。
*テーブル構造、プログラム、1度実行したときのデータ
は、上記サイトを参照してください。
ドットインストール(というプログラム学習サイト)
http://dotinstall.com/lessons/basic_php_advanced/6903
と全く同じ(DBへの接続部分だけ違います)
のですが。
テーブルの定義かとも思ったのですが、
id:int(11)で作成しています。
なぜだかわかりません。
よろしくお願いします。
テーブルを作った時に UNIQUE KEY 制約を設定していないと予想されるので、そういう挙動になります。
例えば、users.name でユニーク制約を付ける場合の例を以下で説明します。
まず、テーブルを以下の SQL で作成します。
/* database.sql */ CREATE DATABASE IF NOT EXISTS hatena_question; GRANT ALL PRIVILEGES ON hatena_question.* TO hatena@localhost IDENTIFIED BY 'hatena'; FLUSH PRIVILEGES; USE hatena_question; CREATE TABLE IF NOT EXISTS `users`( `id` INT AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `email` VARCHAR(255) NOT NULL, `password` VARCHAR(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`) ) engine=InnoDB CHARACTER SET utf8;
これを以下のコマンドで実行するとデータベース、テーブル、ユーザーが作成できます。
mysql -u root -p < database.sql
次は PHP です。
<?php /** Main.php */ try { $dbh = new PDO('mysql:host=localhost;dbname=hatena_question','hatena', 'hatena'); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $dbh->prepare("insert into users (name,email,password) values (:name,:email,:password)"); $stmt->execute(array(":name"=>"n2",":email"=>"e2",":password"=>"p2")); echo "done"; } catch (PDOException $e) { echo($e->getMessage()); exit; }
これをコマンドラインで実行すると2度目からは DUPLICATE entry でエラーになります。
$ php Main.php SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'n2' for key 'name'
すでにレコードが存在していたら更新するようにしたい場合、MySQL の場合は以下のように SQL を変更すると実現できます。
<?php try { $dbh = new PDO('mysql:host=localhost;dbname=hatena_question','hatena', 'hatena'); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $dbh->prepare("INSERT INTO users (name,email,password) VALUES (:name,:email,:password) ON DUPLICATE KEY UPDATE email = VALUES(email), password = VALUES(password)"); $stmt->execute(array(":name"=>"n2",":email"=>"e2",":password"=>"p2")); echo "done"; } catch (PDOException $e) { echo($e->getMessage()); exit; }
余計なお世話かもしれませんが、ドットインストールの該当の動画はちょろっと見ただけですけども、品質が高くないので別のコンテンツで学習した方が良さそうに思います…。
根本的な解決策ではないかも知れませんが、nameにユニークキーを付ければいいですね。
alter table tablename add unique key (name);
テーブルを作った時に UNIQUE KEY 制約を設定していないと予想されるので、そういう挙動になります。
例えば、users.name でユニーク制約を付ける場合の例を以下で説明します。
まず、テーブルを以下の SQL で作成します。
/* database.sql */ CREATE DATABASE IF NOT EXISTS hatena_question; GRANT ALL PRIVILEGES ON hatena_question.* TO hatena@localhost IDENTIFIED BY 'hatena'; FLUSH PRIVILEGES; USE hatena_question; CREATE TABLE IF NOT EXISTS `users`( `id` INT AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `email` VARCHAR(255) NOT NULL, `password` VARCHAR(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`) ) engine=InnoDB CHARACTER SET utf8;
これを以下のコマンドで実行するとデータベース、テーブル、ユーザーが作成できます。
mysql -u root -p < database.sql
次は PHP です。
<?php /** Main.php */ try { $dbh = new PDO('mysql:host=localhost;dbname=hatena_question','hatena', 'hatena'); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $dbh->prepare("insert into users (name,email,password) values (:name,:email,:password)"); $stmt->execute(array(":name"=>"n2",":email"=>"e2",":password"=>"p2")); echo "done"; } catch (PDOException $e) { echo($e->getMessage()); exit; }
これをコマンドラインで実行すると2度目からは DUPLICATE entry でエラーになります。
$ php Main.php SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'n2' for key 'name'
すでにレコードが存在していたら更新するようにしたい場合、MySQL の場合は以下のように SQL を変更すると実現できます。
<?php try { $dbh = new PDO('mysql:host=localhost;dbname=hatena_question','hatena', 'hatena'); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $dbh->prepare("INSERT INTO users (name,email,password) VALUES (:name,:email,:password) ON DUPLICATE KEY UPDATE email = VALUES(email), password = VALUES(password)"); $stmt->execute(array(":name"=>"n2",":email"=>"e2",":password"=>"p2")); echo "done"; } catch (PDOException $e) { echo($e->getMessage()); exit; }
余計なお世話かもしれませんが、ドットインストールの該当の動画はちょろっと見ただけですけども、品質が高くないので別のコンテンツで学習した方が良さそうに思います…。
ありがとうございました。できました。
>ドットインストール
僕のレベルだと丁度いいのかもしれませんね。
ありがとうございました。できました。
2015/04/18 20:51:24>ドットインストール
僕のレベルだと丁度いいのかもしれませんね。