SQL ステートメントのテーブル間でフィールド値をコピーする際にいくつかの問題が発生しました - mysql に基づく

黄舟
リリース: 2017-03-06 11:51:16
オリジナル
1190 人が閲覧しました

しばらく庭に行っていなかったので、あっという間に2017年も3月になってしまいましたが、最近は忙しくてブログも書けず(実は怠け者です)、そんな感じです。恥ずかしい。昨日、退勤前に技術担当の上司が突然テーブル構造を変更したいと言い、あるテーブルのフィールド値を別のテーブルの特定のフィールドにコピーできるかどうか尋ねてきました。ほんの一口ですが、実際にはテーブル間の値のコピーでした。ということで、昨夜残業してBaiduを少し検索してローカルで試してみたので、備忘録としてこのSQL文を書き留めておきます。

1、背景と要件

2 つのテーブル a_user と b_user の構造は次のとおりです:

a_user

+--------+-------------+------+-----+---------+----------------+
| Field    | Type          | Null  |  Key | Default | Extra             |
+--------+-------------+------+-----+---------+----------------+
| id_a     | int(11)       | NO   |  PRI | NULL    | auto_increment|
| a_name| varchar(45)| YES  |        | NULL     |                     |
+--------+-------------+------+-----+---------+----------------+
ログイン後にコピー

b_user

+--------+-------------+------+-----+---------+----------------+
| Field    | Type          | Null  | Key  | Default | Extra          |
+--------+-------------+------+-----+---------+----------------+
| id_b     | int(11)       | NO   | PRI  | NULL    |auto_increment|
| a_id     | int(11)       | NO   | MUL | NULL    |                      |
| b_name| varchar(45)| YES  |        | NULL    |                      |
+--------+-------------+------+-----+---------+----------------+
ログイン後にコピー

2 つのテーブル間の関係: テーブル b_user の a_id 外部キーテーブル a_user の主キー id_a を参照します。

レコードは次のとおりです:

a_user

+------+--------+
| id_a | a_name |
+------+--------+
|    1      |            |
|    2      |            |
|    3      |            |
|    4      |            |
+------+--------+
ログイン後にコピー

b_user

+------+------+--------+
| id_b | a_id | b_name |
+------+------+--------+
|    1      |    1      | 张三   |
|    2      |    2      | 李四   |
|    3      |    2      | 李四   |
|    4      |    3      | 王五   |
|    5      |    3      | 王五   |
|    6      |    3      | 王五   |
|    7      |    4      | 赵六   |
|    8      |    4      | 赵六   |
+------+------+--------+
ログイン後にコピー

要件: b_user テーブルの b_name フィールドの値を a_user テーブルの a_name にコピーします。

2、Baidu で発生した問題を解決してください

Baidu、この SQL ステートメントがより信頼できることがわかりました:

update a_user set a_name = (select b_name from b_user where id_a = a_id);
ログイン後にコピー

このステートメントは、おそらくテーブル a_user フィールドの a_name の更新を参照しています。テーブル b_user の b_name フィールドの値が値のソースとして使用されますが、上記のステートメントが直接実行されると、mysql は次のようにエラーを報告します:


ERROR 1242 (21000): Subquery returns more than 1 row
ログイン後にコピー


これは、update ステートメントが期待していることを意味します。データソースの行数は a_user テーブルと同じになります。 4 の行数は同じですが、上記のサブクエリの結果は...、待て、上記のサブクエリは実行できますか?もちろん違います。実際、上記のサブクエリは


select b_name from b_user left join a_user on a_id = id_a;
ログイン後にコピー


と同等ですが、返される結果は 8 行であり、テーブル a_user の行数とは異なります。

(1) データソースから重複行を削除します

次に、最初にこの問題を解決し、重複レコードを削除します: select distinct a_id, b_name from b_user left jo でa_user on a_id = id_a; 返される結果は次のとおりです。

+------+--------+
| a_id | b_name |
+------+--------+
|    1 | 张三   |
|    2 | 李四   |
|    3 | 王五   |
|    4 | 赵六   |
+------+--------+
ログイン後にコピー

次のステートメントを実行すると、エラーが報告されます。では、上記の結果が b_name のみを含む列になったらどうなるでしょうか?


(2) Distinct を使用して a_id による重複行を削除すると、余分な a_id 列ができます


これは簡単に解決できます。サブクエリを再度ネストするだけです。もう一度 update ステートメントを試してみます

1 update a_user set a_name = (select distinct a_id, b_name from b_user left join a_user on a_id = id_a);
2 ERROR 1241 (21000): Operand should contain 1 column(s)
ログイン後にコピー

奇妙なことに、上記のサブクエリ

select
b_name

from

(
select

) は、サブクエリの結果が上記で報告された更新された行の数と一致していないことがわかります。 unique

a_id, b_name

from
b_user

left


join

a_user

on a_id = id_a) t; 結果は次のようになります:

select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t;
ログイン後にコピー
重複行は削除されていませんか? (3) サブクエリのネストと SQL ステートメントの実行シーケンス 上記の問題を分析してください: ここで、外側の select ステートメントは、クエリするためのデータ ソースとして内側の select ステートメントを使用します。そして、外側の選択は個別に実行すると期待される結果を返すことができるのに、更新の実行時に次のように表示されるのはなぜですか: ERROR 1242 (21000): Subquery

returns

more than

1

row ?

以下は私の推測です: update ステートメントは行ごとに実行されるため、最初のレコードが更新されると、update は select サブクエリから最初のレコードに対応するデータを取得することを期待します。つまり、update です。 a_user set a_name = value source where id_a = a_id; 次に、修飾するために where ステートメントを追加する必要があります:

1 update a_user set a_name = (select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t);
2 ERROR 1242 (21000): Subquery returns more than 1 row
ログイン後にコピー
これで、結果は次のようになります:

+--------+
| b_name |
+--------+
| 张三   |
| 李四   |
| 王五   |
| 赵六   |
+--------+
ログイン後にコピー

3、結果を書きましょう


まずここに、最後の文は

update a_user set a_name = (select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t where 
t.a_id = id_a);
ログイン後にコピー

正直に言うと、まだ不安です。これには、SQL のネストされたクエリ、SQL ステートメントの実行シーケンス、更新ステートメントの実行プロセス、およびその他の SQL の知識が含まれます。つまり、私は Baidu と自分の間違いに頼って SQL を作成しましたが、ローカルでテストしただけで、テストしませんでした。実稼働環境で使用する場合、この SQL の実行効率についてはわかりません。最初に記録を作成し、後で検討します。データベースを専門とする学生の方からアドバイスをいただければ幸いです。

上記は、SQL ステートメント内のテーブル間でフィールド値をコピーする際に発生するいくつかの問題です。これは、mysql の内容に基づいています。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート