Postgres DB-Befehl Fehler mit "IF EXISTS"

Hi,

vermutlich ein sehr leichter Fehler, aber ich komme nicht dahinter.
Fehlermeldung

ERROR: FEHLER: Syntaxfehler bei »IF« LINE 2: IF EXISTS(select * from hd_here.physical_width where hd_... ^ SQL state: 42601 Character: 11

hilft mir auch nicht weiter.

Bin bisher leider nur MySQL gewöhnt und bin mir momentan nicht sicher, ob ich einen groben Denkfehler mache oder das bei Postgres-DBen einfach anders funktioniert.

Mein Code:

BEGIN
    IF EXISTS(select * from hd_here.physical_width where hd_here.physical_width.lane_id = '0') THEN
        INSERT into public.hd_link_validation (link_id, a_o_lanes, avg_lane_width_0) VALUES (hd_here.physical_width.lane_group_id, hd_here.physical_width.lane_id, hd_here.physical_width.value)
    END IF

    IF EXISTS(select * from hd_here.physical_width where hd_here.physical_width.lane_id = '1') THEN
        UPDATE public.hd_link_validation SET ao_lanes ='1', avg_lane_width_1 = hd_here.physical_width.value WHERE id = hd_here.physical_width.lane_group_id
	ELSE
	    UPDATE public.hd_link_validation SET ao_lanes ='0', avg_lane_width_1 = '0' WHERE id = hd_here.physical_width.lane_group_id
    END IF

    IF EXISTS(select * from hd_here.physical_width where hd_here.physical_width.lane_id = '2') THEN
        UPDATE public.hd_link_validation SET ao_lanes ='2', avg_lane_width_2 = hd_here.physical_width.value WHERE id = hd_here.physical_width.lane_group_id
	ELSE
	    UPDATE public.hd_link_validation SET ao_lanes ='1', avg_lane_width_2 = '0' WHERE id = hd_here.physical_width.lane_group_id
    END IF

    IF EXISTS(select * from hd_here.physical_width where hd_here.physical_width.lane_id = '3') THEN
        UPDATE public.hd_link_validation SET ao_lanes ='3', avg_lane_width_3 = hd_here.physical_width.value WHERE id = hd_here.physical_width.lane_group_id
	ELSE
	    UPDATE public.hd_link_validation SET ao_lanes ='2', avg_lane_width_3 = '0' WHERE id = hd_here.physical_width.lane_group_id
    END IF
END;

Was ich versuche:
Die Tabelle “hd_link_validation” (Schema: public) zu befüllen.

Die Tabelle hat folgende Struktur:

link_id(PK)|a_o_lanes|curvature|predecessor|assesor|avg_road_width|avg_lane_width_0|avg_lane_width_1|avg_lane_width_2|avg_lane_width_3

Die Daten sind in den anderen Tabellen des Schemas “hd_here” vorhanden.
Bspw. in der Tabelle “physical_width”
Mehrere Datensätze in Physical_width können bspw. so aussehen:

...|lane_group_id|lane_id|value|...
...|1|0|3.7|...
...|1|1|3.5|...
...|1|2|3.6|...
...|2|0|3.6|...
...|2|1|3.6|...

Wer die Anwendung verstehen will:
“HD_Link_Validation” soll Autobahnabschnitte speichern, dazu die gesamte Anzahl von Spuren, die durchschnittliche Fahrbahnbreite und die durchschnittliche Breite der einzelnen Spuren (0 bis 3). Spur 0 ist der Standstreifen, Spur 1-3 sind die Fahrspuren. Da nicht jede Fahrspur vorhanden ist, wird mit “IF EXISTS” und “ELSE” gearbeitet. In “physical_width” stehen die breiten einzelner Spuren (lane_id). Die “lane_group_id” bündelt mehrere Spuren zu einem Autobahnabschnitt.

Für meine Untersuchung (maschinelles Lernen) brauche ich aber die Daten in einer anderen Struktur (abhängig nur von der lane_group_id), also in der Struktur, die ich in “HD_Link_Validation” vorgegeben habe. Ich möchte dafür einfach nur die Daten (aus anderen Tabellen werden auch noch Infos abgeleitet) so aufbereiten, dass alle Merkmale dafür vorliegen, die ich für ein einfaches Modell brauche.

IF oder BEGIN sind keine SQL Befehle, sondern PL/pgSQL Anweisungen. Wenn das nicht Teil einer Funktion/Prozedur ist, dann klappt das so sowieso nicht. Wenn das Teil einer Funktion ist, dann zeig uns bitte den komplette code.

Letztendlich brauchst Du aber gar kein IF EXISTS. Wenn ich das richtig verstehe kannst Du das durch INSERT ON CONFLICT DO NOTHING bzw. INSERT ON CONFLICT DO UPDATE ersetzen.

Ein paar Anmerkungen:

  1. Ein Begin/End könnte auch ein anonymer Block sein. Ich weiß nicht seit wann mySQL das könnte (vielleicht >8?), pg kann es jedenfalls schon ewig. Nur nicht so, wie hier geschrieben
  2. Wenn 1, dann würde auch ein if then else funktionieren
  3. Es wäre aber wie schon geschrieben tatsächlich nicht nötig
  4. Es wäre wahrscheinlich auch keine Kleinklein mit on conflict nötig
  5. Auch wenn ich den Sinn des Statements und die Richtigkeit der Einzelschritte bezweifel (vermutlich ist der “Reifegrad” des gezeigt SQL wegen der grundsätzlichen Fehler noch gering), man kann es wahrscheinlich mit einem einzigen aggregierenden Select durchführen, also nur Insert ohne updates, vielleicht mit Case
  6. Wg 5. dann sicher auch schnell(er)

Kann ich das Thema selbst schließen, wenn ich mein Problem inzwischen lösen konnte?

Wenn Du eine Lösung gefunden hast, dann wäre es nur nett, wenn Du sie uns auch verrätst und hier reinschreibst.

Einen Status “gelöst” gibt es hier meines Wissens nach nicht