Hallo, ich habe noch nicht so viele Kenntnisse in der PL/pgSQL Programmierung und stehe vor einem kleinen Problem.
Ich möchte in einer Tabelle einen Update Befehl machen und in einer Spalte den jeweiligen Datensatz-Wert immer um 1 erhöhen (ausgehend vom bisherigen Maximalwert) wenn gewisse Bedinungen erfüllt sind. Das soll dann am Ende mit Hilfe einer Funktion/Prozedur geschehen. Den Update Befehl hab ich wie folgt erstellt:
update tabelle
SET wert= (SELECT MAX(wert) FROM tabelle) +1
where wert IS NULL AND wert2 is NOT NULL;
Im Prinzip soll, wenn die Bedingung erfüllt ist, nach dem Maximum des Wertes “wert” in der Spalte gesucht werden und jeder Datensatz dann um 1 erhöht werden. Aber mit diesem Befehl erreiche ich ja nur das alle Werte am ende den selben um 1 erhöhten Wert haben. Ich möchte aber, dass jede einzelne Zeile um 1 erhöht wird (zB. max wert:5, dann+1=6,+1=7,+1=8,…).
Ist wahrscheinlich einfach zu lösen, finde aber nicht die Lösung
Ich würde die neuen Werte mit Window Funktionen berechnen und das Ergebnis dann verwenden um die Tabelle zu ändern:
with new_numbers as (
select pk_spalte, max(wert) over () + row_number() over () as x
from tabelle t
where t.wert is null
and t.wert2 is not null
)
update tabelle t
set wert = n.x
from new_numbers n
where n.pk_spalte = t.pk_spalte
Auf den maximal wert wird einfach eine sich ständig erhöhende Zahl addiert. Und das Ergebnis wird dann im UPDATE verwendet.
das klingt konzeptionell schlecht durchdacht. Da ist die Frage, in welcher Reihenfolge die Datensätze so neu nummeriert werden sollen. Dann, was passiert, wenn später Datensätze geändert, gelöscht oder eingefügt werden?
test=# select * from texs89;
id | wert
----+------
1 |
2 | 7
3 |
4 |
5 |
(5 rows)
test=*# with x as (select id, max(wert) over(), row_number() over () from texs89) select * from x;
id | max | row_number
----+-----+------------
1 | 7 | 1
2 | 7 | 2
3 | 7 | 3
4 | 7 | 4
5 | 7 | 5
(5 rows)
test=*# with x as (select id, max(wert) over(), row_number() over () from texs89) update texs89 set wert = max+row_number from x where texs89.id=x.id;
UPDATE 5
test=*# select * from texs89;
id | wert
----+------
1 | 8
2 | 9
3 | 10
4 | 11
5 | 12
(5 rows)
Vielen Dank schonmal für die schnellen Antworten, ich glaube ich hab gerade ebenfalls eine Fast-Lösung gefunden. Im Prinzip kann man ja einen Counter i immer um eins erhöhen:
CREATE OR REPLACE FUNCTION generate_nr()
RETURNS BOOLEAN LANGUAGE plpgsql SECURITY DEFINER AS $$
DECLARE
i int=(SELECT MAX(wert)+1 FROM tabelle);
BEGIN
update tabelle
SET wert=i, i=i+1
where wert IS NULL AND wert2 is NOT NULL;
RETURN FOUND;
END;
$$;
Aber irgendwie ist es so nicht ganz korrekt:
ERROR: FEHLER: Spalte »i« von Relation »tabelle« existiert nicht
LINE 2: SET wert=i, i=i+1
Die Antwort ist für SQL Server - so ziemlich die einzige Datenbank bei der es keine klare Trennung zwischen prozeduralen Code (PL/pgSQL) und der Abfragesprache (SQL) gibt. Deswegen darf man da Variablen und prozedurale Sprachkonstrukte munter mit SQL mischen.