Verständnisfrage: INSERT ... ON CONFLICT WHERE

Hallo Forum,

bei folgender Query verstehe ich die Fehlermeldung nicht:

INSERT INTO t_warnmeldung_corona (
		cellid,ewz,sterberate,faelle,todesfaelle,
		faelle_pro_100000,betroffenenrate,datum,faelle_letzte_7_tage_pro_100000,genesene,
		bundesland_nr,regierungsbezirk_nr,landkreis_nr,gemeinde_nr
	) VALUES (1001000,90164,1.940639,876,17,971.562930,0.971563,timestamp with time zone '22.01.2021, 00:00',181.890777,0,0,0,0,0)
ON CONFLICT WHERE (datum = '2021-01-22 00:00:00+01' AND cellid=1001000) DO NOTHING

Die Fehlermeldung lautet:

Fehler in der SQL-Abfrage: FEHLER: Syntaxfehler bei »WHERE«
LINE 6: ON CONFLICT **WHERE (datum = ‘2021-01-22 00:00:00+01’ AND cell…

Was ist falsch?

Ein

select * from t_warnmeldung_corona where (datum = ‘2021-01-22 00:00:00+01’ AND cellid=1001000)

funktioniert.

Danke für die Antworten im Voraus

Jürgen

Wie im Handbuch dokumentiert ist, erwartet ON CONFLICT erwartet den Namen eines (unique) Constraints oder die Liste der Spalten die in einem Unique Constraint enthalten sind. Ein WHERE kann man da nicht verwenden.

Wenn Du also sowohl die TIMESTAMP Spalte als auch cellid “unique” haben willst, musst Du einen entsprechenden Index anlegen:

create unique index on t_warnmeldung_corona (datum, cellid);

dann kannst Du

 ON CONFLICT (datum, cellid) 

verwenden.

Aber einen Timestamp als unique zu definieren finde ich merkwürdig. Die Spalte sollte wohl eher ein DATE sein (schon wegen dem nichtsagenden Namen)

Danke für die Antwort.
Da habe ich wohl das Handbuch falsch verstanden.

Vermutlich hast Du es mit der WHERE Bedingung verwechselt die man im UPDATE Teil angeben kann.

Laut Doku (PostgreSQL-12-Doku) gibt es aber ein WHERE zusammen mit INSERT. Zitat:

INSERT INTO table_name [ AS alias ] [ ( column_name [, …] ) ]
[ OVERRIDING { SYSTEM | USER } VALUE ]
{ DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, …] ) [, …] | query }
[ ON CONFLICT [ conflict_target ] conflict_action ]
[ RETURNING * | output_expression [ [ AS ] output_name ] [, …] ]

where conflict_target can be one of:

( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
ON CONSTRAINT constraint_name

Was ich herausgefunden habe ist, dass man

( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) 

angeben muss. Da meine Datentabelle eine “dumme” Tabelle ist, habe ich eine andere Lösung gefunden. Vor dem Einfügen der Daten frage ich das Datum des ältesten Datensatzes ab. Das funktioniert, weil die Daten täglich zum selben Zeitpunkt erhoben werden.

Das ‘where’ steht da im Text und beschreibt was es für conflict_targets gibt, quasi aus literarischen Gründen und nicht als Teil des Codes.

Grüße Uwe

Ja, aber das ist ein zusätzliches WHERE welches verwendet werden kann, wenn die Spalten (bzw. der Index- oder Constraintname) einen partiellen Index referenzieren, also ein (unique) Index der mit WHERE ... angelegt wurde. Das dient dazu, wenn es mehrere partielle Indizes mit der Spaltenliste gibt, den richtigen auszuwählen.

Moin castorb.

Sorry, für die späte Reaktion.
Danke für Deine Antwort. Jetzt ist mir alles klar und verstehe auch die eingangs vorgetragene Fehlermeldung.