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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

Q&A

解決済

2回答

3238閲覧

php ON DUPLICATE KEY UPDATEについて

earnest_gay

総合スコア615

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

0グッド

1クリップ

投稿2017/01/26 09:22

編集2017/01/26 10:06

user_idがuniqueKeyです。

php

1 $sql = "INSERT IGNORE INTO user_image"; 2 $sql .= " (user_id,file,type,name)"; 3 $sql .= " VALUES ('$id','$file','$file_type','$file_name')"; 4 $sql .= " ON DUPLICATE KEY UPDATE"; 5 $sql .= " file = '$file'"; 6 $sql .= " ,type = '$file_type'"; 7 $sql .= " ,name = '$file_name'"; 8 9 $stmt = $pdo->query($sql);

イメージ説明

user_id 70が画像更新ページなどで処理実行すると
user_id 70は存在するので更新されます。

ちょっとテーブル構造を変えてこんな感じにしようとします。
イメージ説明

しかし、user_idがuniqueKeyなのでid82以降のレコードは追加されることなく更新になってしまうので、

最終的にこうなってしまいます。
イメージ説明

更新対象として、user_idとnameかsizeがuniqueKeyなら、、、ということをしたいんですが、これは極端にsizeもuniqueKeyにするだけで勝手に判断してくれるのでしょうか?


追記

user_idとsizeをuniqueにして試してるのですが、下記のようになってしまいます。

イメージ説明

SQLの部分は下記です。

php

1 2//取得サイズリスト作成 3 for($px=25;$px<=500;$px+=25) { 4 if($px <= 100) { 5 //25px単位 6 $size_list[] = $px; 7 } else { 8 //50px単位 9 if($px % 2 == 0) { 10 $size_list[] = $px; 11 } 12 } 13 } 14 15foreach ($size_list as $key => $value) { 16 17 18 $sql = "INSERT IGNORE INTO user_image"; 19 $sql .= " (user_id,file,type,name,size)"; 20 $sql .= " VALUES ('$id','$file','$file_type','$file_name','$prefix')"; 21 $sql .= " ON DUPLICATE KEY UPDATE"; 22 $sql .= " file = '$file'"; 23 $sql .= " ,type = '$file_type'"; 24 $sql .= " ,name = '$file_name'"; 25} 26 27//で何回か回してます。 28//肝心なのはSQLの部分、、、

イメージ説明

レコードがないときにはインサートされて
レコードがあるときにはUPDATEするには
本質問ではどうすればよいでしょうか?

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

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

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

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

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

turbgraphics200

2017/01/26 09:44

uniqueにする/したい理由はなんでしょうか。
guest

回答2

0

ベストアンサー

複合一意制約の定義方法についてはyambejpさんが回答済ですので別の観点から回答をば。

今回のような一意制約を変更するという行為は、
業務要件に大きなインパクトを与えることを先ず抑えてください。

今回1人のユーザが複数ファイルを登録できるようにしたい、
という要件から一意制約キーの変更に思い至ったと思われますが、
この一意キーの付け方次第で実現できること、
できないことが大きく変わるので仕様について整理する必要があります。

以下に一意制約の定義パターンと、
その際に発生する暗黙的な仕様を浮き彫りにしていきます。

  • ユーザIDで一意

→ 1ユーザ1ファイルしか登録できない。
(恐らく変更前の状態)

  • ユーザID、ファイル名で一意

→ 1ユーザ複数ファイルを登録できる。
同名ファイルを登録した場合は上書きされる。

  • ユーザID、サイズで一意

→ 1ユーザ複数ファイルを登録できる。
同一サイズのファイルを登録した場合は同一サイズのファイルが上書きされる。
つまり名称が違う全然別ファイルでもサイズが被れば上書きされる。
(恐らく質問者様の現状)

  • ユーザID、ファイル名、サイズで一意

→ 1ユーザ複数ファイルを登録できる。
同名、同サイズのファイルを登録した場合のみ上書きされる。
つまりサイズ違いは名前が一緒のファイルでも別物扱いとなる。

  • ユーザIDで一意、かつファイル名で一意(おまけ)

→ 1ユーザ1ファイルしか登録できない。
かつ他のユーザで同名ファイルの登録があるとそのファイルが上書きされる。
(複合一意キーの認識誤りの場合に陥ることがあるミス)


一意制約の付け方次第で、
ここまで暗黙的な仕様が変化するので、
実現したいこと・満たすべき要件をきちんと整理してから作業を行うようにしましょう。

#追記
質問者様のキャプチャ画像今頃目を通してみましたが、
もしかしてユーザIDとサイズそれぞれで一意制約を定義してませんか?

その場合は以前に回答したパターンの内、
4つ目で紹介したような振る舞いとなります。

つまるところ、

  • 1ユーザは1ファイルしか登録できない(同ユーザの2回目以降の登録は常に上書き)
  • 同サイズのファイルは全ユーザ分を含めて1つしか存在できない(サイズが同じファイルがあれば常に上書き)

となってしまいますよ。

投稿2017/01/26 14:41

編集2017/01/27 17:58
Panzer_vor

総合スコア1636

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

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

0

user_idとnameかsizeがuniqueKey

であれば複合unique属性で「user_id,name,size」で
設定してみてはどうでしょうか?

#sample
うまく動かないと言うのでsampleつけときます

SQL

1create table tbl(id int not null primary key auto_increment 2,uid int,name varchar(20),size int,hoge varchar(20) 3,unique key(uid,name,size));

順次データ投入

SQL

1insert into tbl(uid,name,size,hoge) values(1,'aaa',100,@a:='hoge1') 2on duplicate key update hoge=@a; 3insert into tbl(uid,name,size,hoge) values(1,'aaa',200,@a:='hoge2') 4on duplicate key update hoge=@a;/*uidとnameが一緒だけどsizeが違うのでOK*/ 5insert into tbl(uid,name,size,hoge) values(1,'bbb',100,@a:='hoge3') 6on duplicate key update hoge=@a;/*uidとsizeが一緒だけどnameが違うのでOK*/ 7insert into tbl(uid,name,size,hoge) values(1,'aaa',100,@a:='hoge4') 8on duplicate key update hoge=@a;/*uidとsizeとnameが一緒なのでhogeを更新*/ 9insert into tbl(uid,name,size,hoge) values(2,'aaa',100,@a:='hoge5') 10on duplicate key update hoge=@a;/*sizeとnameが一緒だけどuidが違うのでOK*/ 11

投稿2017/01/26 09:48

編集2017/01/26 10:20
yambejp

総合スコア114583

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

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

退会済みユーザー

退会済みユーザー

2017/01/26 09:55

これ、最初気が付かないんですよねぇ。 私もこちらのサイトで回答いただいてはじめて複数できることを知りました。
earnest_gay

2017/01/26 10:03

すいません、実際にやってみてならないので質問に追加しました。 よければ見ていただけませんか?
yambejp

2017/01/26 10:16

うまくいかないということなのでsampleつけておきました 確認してみてください
Panzer_vor

2017/01/26 12:53

横槍ですが、 要件的にはユーザIDとファイル名で一意なのが適切な気がしてならないですね。 同じユーザが同じファイル名でファイルを登録してるのに、サイズ違いが出ると別物として扱うのはレア過ぎる気がします・・・
Panzer_vor

2017/01/26 12:57

連投で申し訳ないですが・・・ 履歴的にバージョン管理がしたいにしても、サイズ変化だけは履歴管理するとなって微妙ですし^^;
yambejp

2017/01/26 13:27

Panzer_vorさん 確かに言われてみればファイル名が一緒なのに上書きしないというのは あまり理にかなわないですね なんとなく仕様のとおりコードを書いてしまいましたが 仕様を見直すことも時には必要ですね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問