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

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

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

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

3回答

3477閲覧

[SQL]MysqlでテーブルをUPDATEする際に出てくるエラー

key.dev

総合スコア12

MySQL

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

1グッド

1クリップ

投稿2016/11/01 02:41

編集2016/11/01 08:15

###前提・実現したいこと:SQLであるテーブルを、他のテーブルのデータで更新したい
SQLで、以下のようなテーブルのフィールドを、他のテーブルのフィールドのデータで更新したいのですが、エラーが出ており、行き詰っております。

初心者であります故、質問に至らぬ点があるかもしれませんがどうぞよろしくお願いいたします。
###発生している問題・エラーメッセージ

#1242 - Subquery returns more than 1 row

###更新の要領

■更新したいテーブル名:field_data_field_birthday_after _____________________________________________ | entity_id | type | value | ============================================= | 1 | profile-a | 1984-06-12 06:15:45 | | 4 | profile-a | 1985-06-12 06:15:45 | | 7 | profile-a | 1986-06-12 06:15:45 | --------------------------------------------- ■更新の手順 ※文字情報だけだとややこしいので、イメージ図も下に掲載しておきます。 併せてご参照いただけると幸いです。 ①上記「field_data_field_birthday_after」の"entity_id(PRIMARY)"と、 下記テーブル「profile」の"pid(PRIMARY)"とを紐づけます (entity_id:pid=1:1)。 _______________________ | pid | uid | bundle | ======================= | 1 | 1 | profile-a | | 2 | 1 | profile-b | | 3 | 1 | profile-c | | 4 | 2 | profile-a | | 5 | 2 | profile-b | | 6 | 2 | profile-c | | 7 | 3 | profile-a | | 8 | 3 | profile-b | | 9 | 3 | profile-c | ----------------------- ②「profile」内の、①で紐づけられた各レコードと同じuidを持ち、 かつ"bundle"が"profile-c"のレコードを下記のように抽出ます。 _______________________ | pid | uid | bundle | ======================= | 3 | 1 | profile-c | | 6 | 2 | profile-c | | 9 | 3 | profile-c | ----------------------- ③抽出されたレコードの"pid"を、 「field_data_field_birthday_after」の"uid"が同じレコードの"entity_id"に上書きします。これで更新完了です。 ※2016/11/1追記 テーブルの詳細情報について、ご指摘いただきましたので、下記追記させていただきます。 [profileテーブル] ・一つのuidに対してある"profile-■"は一つだけです。 ですので、 (pid, uid, bundle)=(9, 3, profile-c)が存在する一方で、(10, 3, profile-c) が存在するということはありません。 [field_data_field_birthday_after] ・"type"に格納される「profile-■」は「profile-a」のみとなります。また、更新前の"entity_id"と"type"とに格納されているデータの組み合わせは「profileテーブル」の"bundle"と"uid"のデータの組み合わせと一致します。そのため、例えば、field_data_field_birthday_afterテーブルに(2, profile-a, 1984-11-01 00:00:00) というデータが入ることはありません。

イメージ説明

###試したこと
下記のSQLでテーブルをUPDATEしようとしました。

UPDATE field_data_field_birthday_after SET field_data_field_birthday_after.entity_id = (SELECT pid FROM profile JOIN ( SELECT uid FROM profile JOIN (SELECT entity_id AS temp_id FROM field_data_field_birthday_after) AS temp ON profile.pid = temp_id ) AS user ON profile.uid = user.uid WHERE TYPE = 'profile-c');

すると上記にもある「#1242 - Subquery returns more than 1 row」というエラーが返ってきました。

調べたところ、「このエラーは、サブクエリーが最大で 1 行しか返す必要がないにもかかわらず、複数の行を返すステートメントで発生します。」とのことです
(https://dev.mysql.com/doc/refman/5.6/ja/subquery-errors.html)。

ただし、そもそも、私が更新しようとしている行は複数あるため、更新する内容も当然複数あります。
にもかかわらず、何故これがエラーになるのでしょうか?
どなたかご存知であればご教示いただきたく思います。
よろしくお願いいたします。

###MySQL情報

MySQLバージョン 5.0.95
KiyoshiMotoki👍を押しています

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

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

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

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

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

KiyoshiMotoki

2016/11/01 03:27 編集

profile テーブルに uid と bundle が重複するレコードがある場合、どうしたいですか?例えば profile テーブルに、質問文にご提示のレコードに加えて (10, 3, profile-c) というレコードが存在した場合、field_data_field_birthday_after テーブルの entity_id = 7 のレコードは、9 と 10 のどちらに更新すれば良いのか一意に定まらなくなります。
KiyoshiMotoki

2016/11/01 06:03 編集

また、field_data_field_birthday_after テーブルに (2, profile-a, 1984-11-01 00:00:00) というレコードがあった場合、今度は entity_id = 1 とentity_id = 2 の両方のレコードを entity_id = 3 に更新しようとするため、重複キーエラーとなります。
key.dev

2016/11/01 08:18

KiyoshiMotoki様 ご指摘誠にありがとうございます。以下ご指摘いただきました点に関してご回答差し上げます。[profileテーブル] ・一つのuidに対してある"profile-■"は一つだけです。 ですので、 (pid, uid, bundle)=(9, 3, profile-c)が存在する一方で、(10, 3, profile-c) が存在するということはありません。 [field_data_field_birthday_after] ・"type"に格納される「profile-■」は「profile-a」のみとなります。また、更新前の"entity_id"と"type"とに格納されているデータの組み合わせは「profileテーブル」の"bundle"と"uid"のデータの組み合わせと一致します。そのため、例えば、field_data_field_birthday_afterテーブルに(2, profile-a, 1984-11-01 00:00:00) というデータが入ることはありません。
KiyoshiMotoki

2016/11/01 08:25

key.dev様、返答ありがとうございます。その状況ですと、yambejp様の回答で問題ないかと思います。
guest

回答3

0

ベストアンサー

SQL

1update 2field_data_field_birthday_after as t1 3,profile as t2 4,profile as t3 5set t1.entity_id=t3.pid 6where t1.entity_id=t2.pid 7and t2.uid=t3.uid 8and t3.bundle='profile-c'

投稿2016/11/01 03:29

yambejp

総合スコア114581

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

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

key.dev

2016/11/02 05:08

yambejp様 貴重なアドバイス誠にありがとうございます! おかげさまで問題を解決できました。 ※なお、私の場合、下記のように、 「bundle」のところを「type」に置き換えることで正常に動作しました。 update field_data_field_birthday_after as t1 ,profile as t2 ,profile as t3 set t1.entity_id=t3.pid where t1.entity_id=t2.pid and t2.uid=t3.uid and t3.type='profile-c' ここで、下記2点お聞きしたいのですが、 ご教示いただいてもよろしいでしょうか? ①上の、 「field_data_field_birthday_after as t1  ,profile as t2  ,profile as t3」 というように、テーブルが結合(?)されているかと思いますが、 Joinを使わないときとの違いは何でしょうか? ②同じprofileテーブルにt2、t3と別名を振り、 「t2.uid=t3.uid」という条件を追加されていますが、 なぜ「t1.entity_id=t2.pid and t2.type='profile-c'」だけでは不足なのでしょうか? 上の質問について、 私自身でもどういった違いがあるのかなどいろいろ調べてまいりましたが、 まだ、SQLで存じ上げないことも多く、わからずにおります。 初歩的な質問であれば、大変恐縮ですが、 ご教示のほどよろしくお願いいたします。
yambejp

2016/11/02 05:39

>① >Joinを使わないときとの違いは何でしょうか? たんにupdate構文がテーブルの列記をすることが多いからで JOINで良さそうですね update field_data_field_birthday_after as t1 inner join profile as t2 on t1.entity_id=t2.pid inner join profile as t3 on t2.uid=t3.uid set t1.entity_id=t3.pid where t3.bundle='profile-c' >② >なぜ「t1.entity_id=t2.pid and t2.type='profile-c'」だけでは不足なのでしょうか? 今回の処理は以下のSELECT文を実行してみてください select * from field_data_field_birthday_after as t1 ,profile as t2 ,profile as t3 where t1.entity_id=t2.pid and t2.uid=t3.uid and t3.bundle='profile-c' 3つのテーブルを上記用の用に結合し、一番左のt1.entory_idを右から3番めのt3.pidに 書き換える処理をしているわけですt2はt1とt3をくっつけるための接着剤です
key.dev

2016/11/02 10:47

とても分かりやすいご説明誠にありがとうございます。 非常に参考になりました。 ところで、私の方法とyambejp様のご回答とを見比べるうちに、 yambejp様のご回答では行われていた、WHERE句でのentity_idとpid、uidとuidとの紐づけの条件が、 私の方法ではそもそも存在しないため(更新値であるSELECT句以下にはありましたが)、 うまく動かなかったのかと思い当たるようになりましたが、この解釈で正しいでしょうか?
yambejp

2016/11/02 11:44

もしかしたら私がコードを読み間違えていたかもしれませんので あまり気にしなくてもよいかと思います
guest

0

以下の結果が複数になるって怒られてますね。1件にならないとupdateする値がバインドできないですので。

SQL

1(SELECT pid 2FROM profile 3JOIN ( 4SELECT uid 5FROM profile 6JOIN (SELECT entity_id AS temp_id FROM field_data_field_birthday_after) AS temp ON profile.pid = temp_id 7) AS user ON profile.uid = user.uid 8WHERE TYPE = 'profile-c'); 9

投稿2016/11/01 03:17

fromageblanc

総合スコア2724

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

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

key.dev

2016/11/02 05:27

fromageblanc様 ご回答ありがとうございます。 >1件にならないとupdateする値がバインドできないですので とのことですが、なぜ複数の結果が返ってくるのではだめなのでしょうか? 私の場合「SELECT pid FROM profile」と、SELECTを使っていることで、 おっしゃるように「1件にならないとupdateする値がバインドできない」要になるのでしょうか...? UPDATE用にデータを持ってくる際に、SELECTを使わない状態で、UPDATEをするということ自体は可能なようですので、疑問に思いました… (例:https://www.ipentec.com/document/document.aspx?page=sql-multi-record-update の例1)
guest

0

とりあえず、文法的な誤りは、entity_id = となっているからではないですか。
=で1つの結果を求めているにもかかわらず、当該サブクエリは複数行を返します。

更新すべき対象を求めるSQLと更新したい行を取得するSQLを適切に分離する必要がありますし、
データベース的にはプライマリキーを更新する設計はなるべく避けるべきです。

投稿2016/11/01 03:16

akio221

総合スコア716

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問