Ich habe folgendes Problem: es geht um eine Tabelle "ansprechpartner", in der zu verschiedenen Personen beliebig viele Ansprechpartner in einer bestimmten Reihenfolge gespeichert werden können. Die besagte Tabelle hat also folgende Spalten:
id: Primärschlüssel der Ansprechpartner in Form eines Serials.
person_id: Fremdschlüssel der Person, der ein Ansprechpartner zugewiesen wird.
reihenfolge: laufende Nummer von 1 aufsteigend, der angibt, in welcher Reihenfolge die verschiedenen Ansprechpartner kontaktiert werden sollen.
name: Name des Ansprechpartners.
Außerdem besitzt die Tabelle einen Unique-Constraint auf die Spalten person_id und reihenfolge, um sicherzustellen, dass jede Reihenfolgennummer pro Person nur einmalig vergeben wird.
Dieser Unique-Constraint macht mir aber das Leben beim Umsortieren der Ansprechpartner schwer, das ich wie folgt implementiert habe (beispielhaft soll Stelle 5 auf Stelle 2 verschoben werden):
Code:
-- alles innerhalb einer Transaktion logischerweise
BEGIN;
-- einen bestimmten Ansprechpartner von Person 4711, dessen id ich kenne, temporär ans Ende der Liste setzen
UPDATE
ansprechpartner
SET
reihenfolge = (SELECT max(reihenfolge) + 2 FROM ansprechpartner WHERE person_id = 4711)
WHERE
id = 1337;
-- alle Positionen zwischen der alten Stelle (5) und der neue (2) um 1 nach hinten versetzen
UPDATE
ansprechpartner
SET
reihenfolge = reihenfolge + 1
WHERE
person_id = 4711 AND
reihenfolge >= 2 AND
reihenfolge <= 5; -- FEHLER
-- temporären Wert auf den richtigen (2) setzen
UPDATE
ansprechpartner
SET
reihenfolge = 2
WHERE
id = 1337;
-- Transaktion abschließen
COMMIT; Beim dritten SQL-Befehl bekomme ich jedoch eine Verletzung des Unique-Constraints gemeldet, obwohl der Zustand, der sich aus dem Befehl heraus ergibt, auch wieder konsistent wäre, da ich ja zuvor den zu verschiebenden Datensatz erstmal temporär ganz nach hinten verschoben habe.
Frage: sieht PostgreSQL das zweite Update-Kommando nicht als einen einheitlichen Befehl an und macht intern doch drei einzelne Updates draus? Denn da wäre ja eine verletzung des Unique-Constraints vorprogrammiert und verständlich.
Was mich auch wundert: wenn ich die Position 2 nach 5 verschiebe, also genau umgekehrt, muss ich ja alle Positionen dazwischen um 1 dekrementieren. Der entsprechende Befehl lautet:
Code:
UPDATE
ansprechpartner
SET
reihenfolge = reihenfolge - 1
WHERE
person_id = 4711 AND
reihenfolge > 2 AND
reihenfolge <= 5; Das funktioniert komischerweise, was meine These untermauern dürfte, dass Postgres mit der kleinsten Position (3) anfängt, sie zu dekrementieren und sich dann nach oben arbeitet. Dabei entstehen ja immer die passenden "Lücken", die dann der nächste Wert ausfüllen kann.
Sehe ich das richtig und wie kann ich das Verschieben trotzdem in einem einzigen SQL-Aufruf implementieren?
Lesezeichen