PHP/MySQLで同じデータを2度書いてします。


環境: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)で作成しています。

なぜだかわかりません。
よろしくお願いします。

回答の条件
  • 1人1回まで
  • 登録:
  • 終了:2015/04/18 20:51:54
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:syamaoka No.2

回答回数21ベストアンサー獲得回数9

ポイント150pt

テーブルを作った時に 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;
}

余計なお世話かもしれませんが、ドットインストールの該当の動画はちょろっと見ただけですけども、品質が高くないので別のコンテンツで学習した方が良さそうに思います…。

id:kohhi

ありがとうございました。できました。

>ドットインストール
僕のレベルだと丁度いいのかもしれませんね。

2015/04/18 20:51:24

その他の回答1件)

id:pogpi No.1

回答回数428ベストアンサー獲得回数59

ポイント100pt

根本的な解決策ではないかも知れませんが、nameにユニークキーを付ければいいですね。
alter table tablename add unique key (name);

id:syamaoka No.2

回答回数21ベストアンサー獲得回数9ここでベストアンサー

ポイント150pt

テーブルを作った時に 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;
}

余計なお世話かもしれませんが、ドットインストールの該当の動画はちょろっと見ただけですけども、品質が高くないので別のコンテンツで学習した方が良さそうに思います…。

id:kohhi

ありがとうございました。できました。

>ドットインストール
僕のレベルだと丁度いいのかもしれませんね。

2015/04/18 20:51:24

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません