Erhöhen Sie alle Primärschlüsselwerte um 1

7

Wie erhöhe ich alle meine EmployeeIDWerte um eins, wenn es sich um den Primärschlüssel handelt?

Staubhorn
quelle
5
@ RolandoMySQLDBA Warum sind Hausaufgaben nicht zum Thema, nur weil es Hausaufgaben sind? Es ist in Ordnung, Leuten Antworten zu geben, die ihre eigenen Jobs nicht machen können, aber es ist nicht in Ordnung, Leuten Antworten zu geben, die ihre eigenen Hausaufgaben nicht machen können? Ich denke, wir können viel vernünftiger sein .
Aaron Bertrand

Antworten:

10

Ich gehe davon aus, dass es bei dieser Frage darum geht, wie eine Reihe von Zeilen auf einen höheren Wert aktualisiert werden kann, ohne aufeinander zu treten. Wenn Sie id = 1 in der ersten Zeile auf id = 2 aktualisieren, während die zweite Zeile (mit id = 2) noch vorhanden ist, wird eine Primärschlüsselverletzung angezeigt, da Sie jetzt zwei Zeilen mit id = 2 haben.

Um diese Art von Kollision zu verhindern, müssen Sie nur mit dem größten Wert beginnen und ihn um eins erhöhen. Dies eröffnet eine Lücke für den zweitgrößten Wert, in die sich der drittgrößte Wert bewegen kann, und so weiter.

In SQL Server brauchen Sie sich jedoch keine Sorgen zu machen, da die Engine dies automatisch erledigt:

SQL Fiddle

MS SQL Server 2008 Schema-Setup :

CREATE TABLE dbo.Employee(Id INT PRIMARY KEY CLUSTERED, Name NVARCHAR(MAX));

INSERT INTO dbo.Employee(Id,Name)
VALUES(1,'John'),(2,'Jane'),(3,'Max');

Abfrage 1 :

SELECT * FROM dbo.Employee;

Ergebnisse :

| ID | NAME |
|----|------|
|  1 | John |
|  2 | Jane |
|  3 |  Max |

Abfrage 2 :

UPDATE dbo.Employee
  SET Id = Id + 1;

Ausführungsplan

Abfrage 3 :

SELECT * FROM dbo.Employee;

Ergebnisse :

| ID | NAME |
|----|------|
|  2 | John |
|  3 | Jane |
|  4 |  Max |

Abfrage 4 :

UPDATE dbo.Employee
  SET Id = Id - 1;

Ausführungsplan

Abfrage 5 :

SELECT * FROM dbo.Employee;

Ergebnisse :

| ID | NAME |
|----|------|
|  1 | John |
|  2 | Jane |
|  3 |  Max |

Wenn Sie tatsächlich dem Link SQL Fiddle folgen , können Sie auch die Ausführungspläne für die beiden Update-Anweisungen anzeigen. Der erste sieht so aus:

Geben Sie hier die Bildbeschreibung ein

Dort sieht man ziemlich weit links einen Table SpoolOperator. Dieser Operator erstellt im Grunde genommen eine Kopie aller Zeilen, die aktualisiert wurden, bevor sie vom eigentlichen Operator "Clustered Index Update" daneben zurückgeschrieben werden. Aus diesem Grund kann SQL Server "überlappende" Updates verarbeiten, ohne über sich selbst zu stolpern.

Ein zusätzlicher Vorteil (und der ursprüngliche Grund, warum dieses Verhalten implementiert wurde) ist, dass dieser zweistufige Ansatz Halloween-Schutz bietet .

Sebastian Meine
quelle
2
Die Tabellenspule wird benötigt, da die Namensspalte ein LOB-Typ ist. Mit einem Nicht-LOB-Namen bietet die Sortierung eine ausreichende Phasentrennung für HP. Der Split-Sort-Collapse optimiert die Protokollierung und stellt sicher, dass Änderungen in einer Reihenfolge angewendet werden, die vorübergehende Schlüsselverletzungen verhindert.
Paul White 9
@ PaulWhite, danke für den klarstellenden Kommentar. Sie sprechen in Ihrem kurzen Satz oben einige Konzepte an. Geht einer von euch Artikeln detaillierter?
Sebastian Meine
2
Ich musste nachsehen, aber ja! Ich diskutiere Split-Sort-Collapse in diesem Beitrag und Halloween Protection in einer vierteiligen Serie . Conor Cunningham spricht in seinem Kapitel des SQL Server 2008 Internals-Buches von MS Press über die Optimierung der Protokollierung.
Paul White 9
4

Ohne weitere Details zur Struktur Ihrer Datenbank gibt es hier eine große Anzahl von Variablen.

Wenn eine andere Tabelle, die die Mitarbeiter-IDs als Referenz auf diese Tabelle und die Forgeign-Schlüssel enthält, ordnungsgemäß eingerichtet und so eingestellt ist, dass sie ON UPDATE CASCADEeinfach ausgeführt UPDATE EmployeeTable SET EmployeeID = EmployeeID + 1wird, reicht dies aus - die FK-Beziehungen aktualisieren alles andere nach Bedarf. Ohne ON UPDATE CASCADEin diesem Fall erhalten Sie Fehler und die Anweisung schlägt fehl.

Wenn Sie Tabellen haben, die auf die Mitarbeiter-ID verweisen, ohne dass Einschränkungen für gefälschte Schlüssel vorhanden sind, müssen Sie diese ebenfalls mit aktualisieren UPDATE AnotherTable SET EmployeeID = EmployeeID + 1. Sie sollten alle Tabellenaktualisierungen in einer einzigen Transaktion zusammenfassen (mit Fehlerbehandlung, um sicherzustellen, dass die Transaktion zurückgesetzt wird oder SET XACT_ABORT ONwenn Sie keine genauere Kontrolle über diesen Prozess benötigen), um die Konsistenz aufrechtzuerhalten (wenn also etwas fehlschlägt, wird alles gerollt zurück).

Ich würde fragen, warum Sie dies jemals tun möchten. Eine Mitarbeiter-ID ist im Allgemeinen ein Ersatzschlüssel (auch als Pseudo-Schlüssel bezeichnet), der außer der Identifizierung einer bestimmten Person keine Bedeutung hat (es könnte sich leicht um eine UUID handeln, die in eine Zahl eingebettet ist, mit Ausnahme der Tatsache, dass sie wahrscheinlich in der realen Welt verwendet wird) nach unten, so wäre eine UUID nicht bequem). Weitere Informationen hierzu finden Sie im Kapitel "Pseudo-Key Neat-Freak" in SQL Antipatterns.

David Spillett
quelle