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

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

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

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

Q&A

解決済

3回答

5801閲覧

【PHP + MySQL】UNIQUE制約の付いているカラムへの重複するデータのINSERTの正しいやり方を教えてください。

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

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

2グッド

0クリップ

投稿2017/06/01 12:46

編集2017/06/02 01:00

プログラミングをやり始めて少しの初心者です。質問に至らぬところがございましたら申し訳ございません。

現在 PHPとMySQLを使用してプログラミングの勉強をしています。
そして先程データベースをどのようにするのかを考えながら試していた所、重複するデータを多くINSERTしていることが分かりました。

重複するデータを挿入することが多くなってしまう場合、それは、データベースで重複を阻止するのか、PHPで重複を阻止するのかどちらでやるべきなのか。どのようにしたら良いのでしょうか。

現在MySQLを使用しており、その列をUNIQUEにすることで、重複するデータが入ることはなくなりましたが、このPHPのプログラムではDuplicatedな値を多くINSERTしてしまっています。

プログラムを1度動かすと 1割程が新規にINSERTされて残りの、9割程がDuplicatedな値をINSERTしてしまっています。この場合、Duplicatedな値をMySQLへINSERTするのではなくて、PHPで一度処理をしてからMySQLへINSERTするのが良いのでしょうか?

※追記です
自分で読み直したらわかりにくかったため追記をさせていただきます。

PHP(9割重複したデータ) → MySQL(UNIQUE)
・UNIQUEなので重複したデータはテーブルには入っていないが、入らないデータが多くINSERTされていることが不安

PHP(ここで重複を取り除く) → MySQL(UNIQUE)
・MySQLの方に重複処理を任せたほうがいいのかのかどうなのか。(Uniqueに任せる)

この2つのやり方どちらでやるのか正解なのかを知りたいです。

s8_chu, ikuwow👍を押しています

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

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

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

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

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

mpyw

2017/06/01 13:02

Duplicatedですね
退会済みユーザー

退会済みユーザー

2017/06/01 13:13

ありがとうございます。修正させていただきました。
guest

回答3

0

ベストアンサー

PostgreSQLのように任意の式による制約を設けられるRDBMSの場合は「データベース側にバリデーションを集中させる」という運用は一つの選択肢にはなると思います。

MySQLの場合は外部キー制約とユニークキー制約程度しか付けられないので、「アプリケーション側でバリデーションし、データベース側の制約は万が一のための保険にする」という運用にせざるを得ないです。

ただし、アプリケーション側でバリデーションする場合は「ほぼ同時にリクエストが飛んできた場合」を考慮する必要があります。以下のように入り交じるケースがあるからです。

ユーザAによる存在確認

ユーザBによる存在確認

ユーザAによる挿入処理(成功)

ユーザBによる挿入処理(重複orユニーク制約により失敗)

SELECT ... FOR UPDATE でロックをかけながら行選択すると、存在しなかった場合には他のリクエストによるテーブルへの挿入処理およびその未存在のレコードに対する選択処理がブロックされるので、このやり方でも安全性を担保することはできます。ただしパフォーマンスは低下する可能性があるので、ロックせずにSELECTし、「万が一競合したらユニーク制約のエラーに拾ってもらう」というやり方でもいいです。

投稿2017/06/01 13:08

編集2017/06/01 13:26
mpyw

総合スコア5223

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

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

退会済みユーザー

退会済みユーザー

2017/06/01 17:24 編集

修正とともに回答、ありがとうございます。おそらくこの回答を知りたくて質問をさせていただいたのだと思います。 MySQLを使用している場合は悪例だとは思いますが。 質問の > PHP(ここで重複を取り除く) → MySQL(UNIQUE) をするほうが良いということがわかりました。 PostgreSQLは聞いたことはあるのですがPostgreSQLを使用すれば、又別の方法も考えうることができるということなのですね。 とても知りたいことをここまで素早く教えて頂きありがとうございました。
guest

0

がると申します。

少しまとめますと。
・データが複数ある
・「複数ある」データの何割かは「重複するデータ」である
・「重複するデータ」は、INSERTさせたくない

という前提があって。
上述に対して

・PHP側でチェックして取り除くか
・DB側でUNIQUE制約ではじくか

のどちらがよいか? という疑問だと思われますが、上述で認識はあってますでしょうか?

個人的には、という前置きを置きまして。
「滅多に重複しないんだけど、ごくまれに重複することがあり得る」くらいですと「INSERT前のチェックは特にせず、INSERT時に失敗したら(一応エラー内容を確認しつつ)適宜対応」というロジックを書く事が多いのですが。

「9割程がDuplicatedな値をINSERTしてしまっています」という状態で、かつ「Duplicatedな値はINSERTしたくない」のであれば
・まずINSERTする前にPHP側でチェックをして「明らかに重複しているデータは、INSERT対象外にする」
・かつ「UNIQUE制約」は行い、瀬戸際もしっかりとガードする
というロジックを、私なら書くかなぁ、と思いました。

「正解」というのも色々あろうかと思うので、個人的な見解を書かせていただきました。
以上、何かの参考になれば幸いです。

投稿2017/06/01 13:15

gallu

総合スコア506

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

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

退会済みユーザー

退会済みユーザー

2017/06/01 17:24 編集

回答して頂きありがとうございます。回答を読ましていただきました。 > 上述で認識はあってますでしょうか? まさにその通りのことです。 ガル様の対処例を教えて頂きありがとうございます。mpywさん同様アプリケーション側でやはりチェックをする方がよいという方向だということがわかりました。大変参考になりました、ありがとうございます。
guest

0

テーブルにユニークなカラム(主キーまたはユニークキー属性のあるカラム)が
あれば重複は起こりません
逆にユニークなカラムがなければSQL側で制限するのには工夫が必要です。

投稿2017/06/01 12:49

yambejp

総合スコア114585

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

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

退会済みユーザー

退会済みユーザー

2017/06/01 17:24 編集

回答ありがとうございます。現在は ALTER TABLE `テーブル名` ADD UNIQUE("カラム")を行っていました。 INSERTしてもデータが増えない場合は重複だと考えております。
mpyw

2017/06/01 13:24 編集

INSERT IGNORE じゃないとユニーク制約に引っかかった場合エラーになるはずですが、PDOのエラーモードは設定されていないのでしょうか?デフォルトだと不具合の原因になりやすいのでPDOExceptionが飛ぶようにすべきだと思います。
yambejp

2017/06/01 13:10

そうですね、 INSERT IGNORE INTO構文で処理すればユニークなカラムに弾かれます 逆に INSERT INTO ON DUPULICATE KEY UPDATE構文を利用すれば あとから来たデータは既存のデータを上書きします いずれにしろユニーク属性を利用して重複データが二重登録されることは ありません
退会済みユーザー

退会済みユーザー

2017/06/01 17:25 編集

ありがとうございます。 正しい使い方をしていたのかも全くわからないのですが、ほとんどエラーを回避する目的でON DUPLICATE KEY UPDATEを使用してそのカラムを同じものへ更新をしておりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問