Was passiert in einer UPDATE-Anweisung, in der die aktualisierte Tabelle in den FROM / JOIN-Klauseln nicht erwähnt wird?

8

Ich wollte die folgende UPDATE -Anweisung in einer SQL Server-Datenbanktabelle ausführen:

%Vor%

Aus Versehen habe ich stattdessen die folgende Anweisung ausgeführt:

%Vor%

Beachten Sie, dass in dieser zweiten Anweisung (die falsche) die Klausel FROM die Tabelle TABLE_A_COPY anstelle von TABLE_A angibt. Beide Tabellen haben genau dasselbe Schema (d. H. Dieselben Spalten) und dieselben Daten (vor der Ausführung von UPDATE ).

Sowohl TABLE_A als auch TABLE_A_COPY haben ungefähr 100 Millionen Datensätze und das Update betrifft ungefähr 500.000 Datensätze. Die zweite Anweisung (die falsche) läuft mehrere Stunden lang und schlägt fehl, während die erste Anweisung (die richtige) 40 Sekunden lang ausgeführt wird und erfolgreich ist.

Offensichtlich sind beide Anweisungen syntaktisch korrekt, aber ich bin mir nicht sicher, was genau ich SQL Server mit der ersten Anweisung zu tun hatte.

Meine Fragen sind:

  1. Was hat SQL Server in der zweiten Anweisung versucht? Bei meinem Fehler habe ich die Verknüpfung zwischen den Datensätzen von TABLE_A bis TABLE_A_COPY nicht angegeben, also habe ich versucht einen CROSS JOIN zwischen den beiden zu machen, und dann jeden Datensatz in TABLE_A a milliardenfach zu aktualisieren?

  2. Wenn es keine allzu große Frage ist, was wäre ein gültiges Szenario für eine solche UPDATE -Anweisung, in der die aktualisierte Tabelle in den FROM/JOIN -Klauseln nicht erwähnt wird. Warum sollte jemand das tun? Warum würde SQL Server das sogar zulassen?

Ich habe versucht, eine Antwort auf meine Fragen zu finden, aber Google scheint zu glauben, dass ich nach UPDATE FROM syntax frage.

    
Ricardo 23.10.2015, 10:54
quelle

2 Antworten

2

1) Es gibt keine Verbindung zwischen TABLE_A und TABLE_A_COPY , so dass Sie CROSS JOIN erhalten und die gleiche Zeile massiv aktualisieren. Das Ergebnis kann nichtdeterministisch sein, wenn die parallele Ausführung aktiviert ist:

LiveDemo

%Vor%

Überprüfen Sie den obigen Code wie TABLE_A Datensatz mit KEY_1 = 6 geändert.

2) SQL Server UPDATE FROM/DELETE FROM -Syntax ist viel breiter als der ANSI-Standard. Das Problem, auf das Sie stoßen, kann auf mehrere Aktualisierungen derselben Zeile reduziert werden. Mit UPDATE erhalten Sie keinen Fehler oder Warnung:

Von Let's deprecate UPDATE FROM! und Deprecate UPDATE FROM and DELETE FROM :

  

Korrektheit? Bah, wen interessiert das?

     

Nun, die meisten tun es. Deshalb testen wir.

     

Wenn ich die Join-Kriterien in einer SELECT-Abfrage durcheinander bringe, so dass zu viele Zeilen   aus dem zweiten Tisch-Match, ich werde es sehen, sobald ich teste, weil ich   bekomme mehr Zeilen zurück als erwartet. Wenn ich die Unterabfragekriterien durcheinander bringe   in einer ANSI-Standard-UPDATE-Abfrage in ähnlicher Weise sehe ich es sogar   früher, weil SQL Server bei der Unterabfrage einen Fehler zurückgibt   gibt mehr als einen einzelnen Wert zurück. Aber mit dem proprietären UPDATE VON   Syntax, ich kann den Beitritt vermasseln und nie bemerken - SQL Server wird   wiederhole die gleiche Zeile immer wieder, wenn sie mehr entspricht   als eine Zeile in der verbundenen Tabelle, mit nur dem Ergebnis des letzten von   diese Updates kleben. Und es gibt keine Möglichkeit zu wissen, welche Zeile das ist   wird sein, da das im Abfrageausführungsplan abhängt, der passiert   Ausgewählt werden. Ein Worst-Case-Szenario wäre eines, bei dem die Ausführung erfolgt   Plan führt zufällig zu dem erwarteten Ergebnis bei allen Tests   auf dem Single-Prozessor-Entwicklungsserver - und dann danach   Bereitstellung auf dem Vier-Wege-Dual-Core-Produktionsserver, unsere wertvolle   Daten treffen plötzlich den Fan ...

Wenn Sie zum Beispiel MERGE verwenden, erhalten Sie eine Fehlermeldung:

  

Die MERGE-Anweisung hat versucht, dieselbe Zeile mehr zu aktualisieren oder zu löschen   als einmal. Dies passiert, wenn eine Zielzeile mehr als einer Quelle entspricht   Reihe. Eine MERGE-Anweisung kann dieselbe Zeile des Ziels nicht aktualisieren / löschen   Tabelle mehrmals. Verfeinern Sie die ON-Klausel, um eine Zielzeile sicherzustellen   passt höchstens zu einer Quellzeile oder gruppiert die GROUP BY-Klausel   die Quellzeilen.

Sie müssen also vorsichtiger sein und Ihren Code überprüfen. Ich möchte auch Fehler bekommen, aber wie Sie in connect Link sehen, wird dies nicht passieren.

Eine Möglichkeit, dies zu vermeiden, ist die Verwendung von UPDATE alias , so dass Sie sicher sind, dass Sie Tabellen verwenden, die an FROM JOIN teilnehmen und keine anderen Tabellen beteiligt sind.:

%Vor%     
lad2025 23.10.2015, 11:34
quelle
0

SQL wird eine Menge Dinge erlauben, die wahrscheinlich keinen Sinn machen Hinweis tableB ist auf beiden Seiten des ein

%Vor%

SQL prüft nur die Syntax - es liegt an Ihnen, also schreiben Sie eine Aussage, die Sinn macht

Es könnte sein, dass Sie wirklich eine Aktualisierung des Produkttyps möchten

So würde ich diese Aussage schreiben Ich richte die Tabellennamen aus, so dass es einfacher ist,

zu sehen %Vor%     
paparazzo 23.10.2015 11:35
quelle

Tags und Links