Maison  >  Article  >  base de données  >  Quelques problèmes rencontrés lors de la copie des valeurs de champ entre les tables dans les instructions SQL - basées sur MySQL

Quelques problèmes rencontrés lors de la copie des valeurs de champ entre les tables dans les instructions SQL - basées sur MySQL

黄舟
黄舟original
2017-03-06 11:51:161181parcourir

Je ne suis pas allée au jardin depuis longtemps. En un clin d'œil, mars 2017 est déjà arrivé. J'ai été trop occupé pour écrire un blog il y a quelque temps (en fait, je suis paresseux), et J'ai tellement honte. Hier, avant de quitter le travail, le responsable technique m'a soudainement dit que je voulais changer la structure des tables et m'a demandé si je pouvais copier les valeurs des champs d'une table dans un certain champ d'une autre table. bouchée, mais c'était en fait un champ inter-tables. J'ai donc fait des heures supplémentaires hier soir et j'ai cherché Baidu pendant un moment, puis je l'ai testé localement et je l'ai fait fonctionner. J'écrirai cette instruction SQL comme rappel.

1. Contexte et exigences

Les structures des deux tables a_user et b_user sont les suivantes :

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    |                      |
+--------+-------------+------+-----+---------+----------------+

La relation entre les deux tables : la clé étrangère a_id de la table b_user fait référence à la clé primaire id_a de la table a_user. Les

enregistrements sont les suivants :

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      | 赵六   |
+------+------+--------+

Exigence : copier la valeur du champ b_name dans la table b_user vers a_name dans la table a_user.

2, Baidu et résoudre les problèmes rencontrés

Baidu vérifié et trouvé Utilisez ceci Instruction SQL pour faciliter les choses :

update a_user set a_name = (select b_name from b_user where id_a = a_id);

Cette instruction signifie probablement mettre à jour le champ a_name de la table a_user et utiliser la valeur du champ b_name dans la table b_user comme source de valeur, mais exécuter directement le MySQL ci-dessus signalera une erreur comme suit :


ERROR 1242 (21000): Subquery returns more than 1 row


signifie que l'instruction de mise à jour attend le nombre de données les lignes source doivent être identiques à Le nombre de lignes dans la table a_user est égal à 4, mais le résultat de la sous-requête ci-dessus est..., attendez, la sous-requête ci-dessus peut-elle être exécutée ? Bien sûr que non. En fait, la sous-requête ci-dessus équivaut à :


select b_name from b_user left join a_user on a_id = id_a;


Mais le résultat qu'elle renvoie est 8 lignes, ce qui est le même comme celui de la table a_user Le nombre de lignes est différent.

(1) Éliminez les lignes en double de la source de données

Ensuite, résolvez d'abord ce problème et supprimez les enregistrements en double : sélectionner distinct a_id, b_name de b_user gauche rejoindre a_user sur a_id = id_a; Le résultat qu'il renvoie est le suivant :

+------+--------+
| a_id | b_name |
+------+--------+
|    1 | 张三   |
|    2 | 李四   |
|    3 | 王五   |
|    4 | 赵六   |
+------+--------+

Le résultat est de 2 colonnes. Si vous exécutez l'instruction suivante, elle signalera une erreur :

.

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)


Alors, comment changer le résultat ci-dessus en une colonne contenant uniquement b_name ?

(2) Après avoir utilisé distinct pour supprimer les lignes en double par a_id, il y a une colonne a_id supplémentaire

Cela peut être facilement résolu par imbrication les sous-requêtes Un seul clic :


select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t;


D'accord, essayez à nouveau l'instruction de mise à jour


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


Vous pouvez voir que le problème d'incohérence entre le résultat de la sous-requête et le nombre de lignes mises à jour a été signalé ci-dessus. Étrange, la sous-requête ci-dessus . select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t; Le résultat est :

+--------+
| b_name |
+--------+
| 张三   |
| 李四   |
| 王五   |
| 赵六   |
+--------+

Les lignes en double n'ont-elles pas été éliminées ?

(3) Imbrication des sous-requêtes et ordre d'exécution des instructions SQL

Analysez le problème ci-dessus : il y a maintenant deux sous-requêtes dans la sélection , la sélection externe utilise la sélection interne comme source de données à interroger. La sélection interne et la sélection externe peuvent renvoyer les résultats attendus lorsqu'elles sont exécutées séparément. Alors pourquoi l'erreur suivante se produit-elle lors de l'exécution de la mise à jour : ERROR 1242 (21000) : la sous-requête renvoie plus de 1 ligne ?

Ce qui suit est ma supposition : l'instruction update est exécutée ligne par ligne, donc lorsque le premier enregistrement est mis à jour, update s'attendra à obtenir un enregistrement correspondant au premier enregistrement de la sélection sous-requête. Données enregistrées, c'est-à-dire mettre à jour a_user set a_name = value source Where id_a = a_id ; alors vous devez ajouter une instruction Where pour qualifier :


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);


Ça y est. Les résultats sont les suivants :

+------+--------+
| id_a | a_name |
+------+--------+
|    1     | 张三   |
|    2     | 李四   |
|    3     | 王五   |
|    4     | 赵六   |
+------+--------+


3, le résultat est

Écrivons-le ici d'abord. La dernière phrase est


<.>
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);

Pour être honnête, je ne suis toujours pas sûr. Cela implique des requêtes imbriquées SQL, la séquence d'exécution des instructions SQL, le processus d'exécution des instructions de mise à jour et d'autres connaissances SQL. En bref, je me suis appuyé sur Baidu et mes propres erreurs pour comprendre un SQL. Cependant, je ne l'ai testé que localement et je ne l'ai pas testé localement. . Pour une utilisation dans un environnement de production, je n'ai aucune idée de l'efficacité d'exécution de ce SQL. Je vais d'abord faire un enregistrement et l'étudier plus tard. J'espère que les étudiants spécialisés dans les bases de données pourront donner quelques conseils.

Ci-dessus sont quelques problèmes rencontrés lors de la copie des valeurs de champ entre les tables dans les instructions SQL - basées sur le contenu MySQL. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn