Heim  >  Artikel  >  Datenbank  >  Beim Kopieren von Feldwerten zwischen Tabellen in SQL-Anweisungen – basierend auf MySQL – sind einige Probleme aufgetreten

Beim Kopieren von Feldwerten zwischen Tabellen in SQL-Anweisungen – basierend auf MySQL – sind einige Probleme aufgetreten

黄舟
黄舟Original
2017-03-06 11:51:161194Durchsuche

Es ist lange her, dass ich das letzte Mal im Garten war. Im Handumdrehen ist es März 2017. Ich war vor einiger Zeit zu beschäftigt, um einen Blog zu schreiben (eigentlich bin ich faul). und ich schäme mich so sehr. Gestern, bevor ich von der Arbeit ging, sagte mir der technische Chef plötzlich, dass ich die Tabellenstruktur ändern wollte, und fragte mich, ob ich die Feldwerte einer Tabelle in ein bestimmtes Feld einer anderen Tabelle kopieren könne Das war ein Bissen, aber es war tatsächlich eine Wertkopie zwischen Tabellen. Also habe ich letzte Nacht Überstunden gemacht und Baidu eine Weile durchsucht und es dann tatsächlich zum Laufen gebracht. Zur Erinnerung werde ich diese SQL-Anweisung aufschreiben.

1. Hintergrund und Anforderungen

Die Strukturen der beiden Tabellen a_user und b_user sind wie folgt:

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

Die Beziehung zwischen den beiden Tabellen: Der Fremdschlüssel a_id der Tabelle b_user bezieht sich auf den Primärschlüssel id_a der Tabelle a_user. Die

-Datensätze lauten wie folgt:

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

Anforderung: Kopieren Sie den Wert des b_name-Felds in der b_user-Tabelle zu a_name in der a_user-Tabelle.

2, Baidu und die aufgetretenen Probleme lösen

Baidu hat dies überprüft und gefunden SQL-Anweisung zur Vereinfachung:

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

Diese Anweisung bedeutet wahrscheinlich, das Feld a_name der Tabelle a_user zu aktualisieren und den Wert des Felds b_name in Tabelle b_user als Wertquelle zu verwenden, aber direkt auszuführen Das obige MySQL meldet einen Fehler wie folgt:


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


bedeutet, dass die Update-Anweisung die Anzahl der Daten erwartet Quellzeilen müssen gleich sein wie Die Anzahl der Zeilen in der a_user-Tabelle ist gleich 4, aber das Ergebnis der obigen Unterabfrage ist ..., warten Sie, kann die obige Unterabfrage ausgeführt werden? Natürlich nicht. Tatsächlich entspricht die obige Unterabfrage:


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


Das zurückgegebene Ergebnis besteht jedoch aus 8 Zeilen, was dasselbe ist wie die der Tabelle a_user Die Anzahl der Zeilen ist unterschiedlich.

(1) Entfernen Sie doppelte Zeilen aus der Datenquelle

Lösen Sie dann zuerst dieses Problem und entfernen Sie die doppelten Datensätze: select distinct a_id, b_name from b_user left join a_user on a_id = id_a; Das zurückgegebene Ergebnis ist wie folgt:

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

Das Ergebnis besteht aus 2 Spalten. Wenn Sie die folgende Anweisung ausführen, wird ein Fehler gemeldet:


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)


Wie kann man also das obige Ergebnis in eine Spalte ändern, die nur b_name enthält?

(2) Nach der Verwendung von „distinct“ zum Entfernen doppelter Zeilen nach a_id gibt es eine zusätzliche a_id-Spalte

Dies kann leicht durch Verschachtelung gelöst werden die Unterabfragen Nur ein Klick:


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


Okay, versuchen Sie es noch einmal mit der Update-Anweisung


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


Sie können sehen, dass das Problem der Inkonsistenz zwischen dem Ergebnis der Unterabfrage und der Anzahl der aktualisierten Zeilen oben gemeldet wurde. Seltsam, die obige Unterabfrage select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t; Das Ergebnis ist:

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

Wurden die doppelten Zeilen nicht entfernt?

(3) Unterabfrageverschachtelung und Ausführungsreihenfolge der SQL-Anweisung

Analysieren Sie das obige Problem: Jetzt gibt es zwei Unterabfragen in der Auswahl Die äußere Auswahl verwendet die innere Auswahl als Datenquelle für die Abfrage. Sowohl die innere Auswahl als auch die äußere Auswahl können die erwarteten Ergebnisse zurückgeben, wenn sie separat ausgeführt werden. Warum tritt beim Ausführen der Aktualisierung der folgende Fehler auf? >1242 (21000): Unterabfrage gibt mehr als 1 Zeile zurück?

Das Folgende ist meine Vermutung: Die Update-Anweisung wird Zeile für Zeile ausgeführt. Wenn also der erste Datensatz aktualisiert wird, erwartet update, dass aus der Auswahl ein Datensatz erhalten wird, der dem ersten Datensatz entspricht Unterabfrage. Aufgezeichnete Daten, d. h. update a_user set a_name = value source where id_a = a_id, dann müssen Sie eine where-Anweisung hinzufügen, um sie zu qualifizieren:


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


Das ist es:

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


3, das Ergebnis Schreiben wir es zuerst hier, der letzte Satz ist


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

Ehrlich gesagt fühle ich mich immer noch unsicher. Dies beinhaltet verschachtelte SQL-Abfragen, die Ausführungssequenz von SQL-Anweisungen, den Ausführungsprozess von Aktualisierungsanweisungen und andere SQL-Kenntnisse. Ich habe mich jedoch auf Baidu und meine eigenen Fehler verlassen, um eine SQL zu erstellen Für den Einsatz vor Ort in einer Produktionsumgebung habe ich keine Ahnung von der Ausführungseffizienz dieses SQL. Ich werde zuerst einen Datensatz erstellen und ihn später untersuchen. Ich hoffe, dass Studenten, die sich auf Datenbanken spezialisiert haben, einige Ratschläge geben können.

Die oben genannten Probleme sind beim Kopieren von Feldwerten zwischen Tabellen in SQL-Anweisungen aufgeführt – basierend auf MySQL-Inhalten. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn